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;
        });
相关文章
相关标签/搜索