zoukankan      html  css  js  c++  java
  • 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是相等的那么结果就跟没排序之前是一样的,但是……

    结果如下:

    ====IE11====

    ====火狐====

    ====Chrome====

    可以看出,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;
            });
    致读者:感谢你阅读本文,请随手点击右下角的推荐或分享,谢谢!
  • 相关阅读:
    jQuery自学笔记(四):jQuery DOM节点操作
    jQuery自学笔记(三):jQuery动画效果
    jQuery自学笔记(二):jQuery选择器
    面试记录与复盘总结
    wh-研发功能复盘
    st项目-要素标记功能的实现以及经验总结
    ST项目经验总结2
    S台项目记录-1
    统计模型项目开发经验汇总
    开发规范
  • 原文地址:https://www.cnblogs.com/yzeng/p/3949182.html
Copyright © 2011-2022 走看看