Chrome谷歌瀏覽器中js代碼Array.sort排序的bug亂序解決辦法

【現象】算法

代碼以下:數組

 var list = [{ n: "a", v: 1 }, { n: "b", v: 1 }, { n: "c", v: 1 }, { n: "d", v: 1 }, { n: "e", v: 1 }, { n: "f", v: 1 }, { n: "g", v: 1 }, { n: "h", v: 1 }, { n: "i", v: 1 }, { n: "j", v: 1 }, { n: "k", v: 1 }, ];
        list.sort(function (a, b) {
            return a.v - b.v;
        });
        for (var i = 0; i < list.length; i++) {
            console.log(list[i].n);
        }

很簡單,就是定一個對象數組,再用sort方法按v字段對其排序,這個問題很容易讓人忽略,由於按正常思惟都會認爲只要全部v是相等的那麼結果就跟沒排序以前是同樣的,可是……測試

結果以下:spa

====IE11====code

====火狐====對象

====Chrome====blog

能夠看出,IE跟火狐都沒問題,但Chrome卻成了亂序。排序

通過查閱資料,網上對這個問題彷佛沒有多少實際的解決辦法。聽說谷歌開發者認爲這不是個bug不予解決,由於V8引擎的緣由,爲了高效排序,稱之爲不穩定排序。其實這也不算是一個BUG,不一樣人會有不一樣的見解:a:"由於排序依據是相同的就是沒有順序,沒有順序就是亂序,這種結果是正確的";b:"既然排序依據是相同的那就按照原始順序輸出"(這應該是大多數據語言裏常規的作法)。網上有牛人說數組超過10條後會調用另外一種排序方法(插入排序),10如下用的是快速排序算法,爲了提交效率,因此會出現這種狀況。索引

網上有人給出了辦法就是相同的狀況下強制產生差別(當順序相同時,讓a比b小):開發

list.sort(function (a, b) {
            return a.v - b.v || -1;
        });

經測試,該方法無效。緣由多是返回值都相同致使。

很苦惱,因而繼續想辦法,既然返回值相同也會出現這個問題,那如何能讓返回值即不相同排序結果還要正確呢?因而通過一番思索,想到了一個值:index,沒錯!就是根據索引來排序,若是順序相同那麼就根據比較索引,索引的順序就是排序前的順序,因而代碼改成:

list.sort(function (a, b) {
            return a.v - b.v || list.indexOf(a)-list.indexOf(b);
        });

測試結果仍然不行。

有些苦惱,仔細想了一下發現:思路是沒有問題,可是在排序中元素位置是不斷髮生變化的,因此indexOf取出的不是原始的索引位置,因此排序仍然不正確。所以按照這個思路去作,在每一個元素里加個屬性來保留它原始的索引,而後再按此索引排序,代碼更改後以下:

for (var i = 0; i < list.length; i++) {
            list[i].oldIndex = i;
        }
        list.sort(function (a, b) {
            return a.v - b.v || a.oldIndex - b.oldIndex;
        });

測試結果沒問題,跟咱們預期的相同!

【解決辦法】

因而正確結果就是:先循環給每一個元素增長一個屬性,用來保存它目前的位置,而後再排序中遇到等序時取索引進行排序

例如:

 

 for (var i = 0; i < list.length; i++) {
            list[i].oldIndex = i;
        }
        list.sort(function (a, b) {
            return a.v - b.v || a.oldIndex - b.oldIndex;
        });
相關文章
相關標籤/搜索