【问题标题】:JavaScript. Array .sort() method returns different results for Chrome and Firefox if array contains duplicate numbersJavaScript。如果数组包含重复数字,则 Array .sort() 方法会为 Chrome 和 Firefox 返回不同的结果
【发布时间】:2017-03-23 19:56:57
【问题描述】:

我有一个包含随机数的数组。当我尝试通过.sort() 方法对该数组进行排序时,如果数组包含重复数字,则结果会有所不同。以下代码在 Chrome 和 Firefox 中的工作方式不同:

[1,2,3,4,5,6,7,8,9,2,15,3,4,5,1,2,3,4,0,2,3].sort(function(a, b) {
  console.log("a=", a, "b=", b)
})

Plunker:http://plnkr.co/edit/Ocm1ZSXgkoCM7FQeH0v5

有问题吗?如何修复此行为以在 Chrome 和 FF 中获得相同的结果?

【问题讨论】:

  • 您的sort 函数错误。由于每次比较都会返回undefined,因此预计排序将不起作用。
  • @vlaz 我已经更新了 plunk
  • @vlaz 请在stackoverflow.com/a/40516655/5397119987654322@@vlaz 下查看我最新的 cmets
  • 我有。你不能用这个函数做你想做的事情。请参阅 here 了解为什么这可能是一个问题。
  • @vlaz 请检查我的答案是否正在做他想做的事情

标签: javascript arrays google-chrome sorting firefox


【解决方案1】:

它适用于适当的返回值。

var array = [1,2,3,4,5,6,7,8,9,2,15,3,4,5,1,2,3,4,0,2,3];

array.sort(function(a, b) {
    return a - b;
});
console.log(array);

array.sort(function(a, b) {
    return (a & 1) - (b & 1) || a - b;
});
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 这段代码在 Chrome 和 FF 的 console.log() 中仍然返回不同的结果
  • 我真的很怀疑
  • @SergioIvanuzzo 结果是一样的。忽略其他输出 - 浏览器只是使用不同的排序算法。
  • @SergioIvanuzzo 那么您希望发生什么?部署了两种不同的排序算法。您的输出将按照您允许的排序进行排序。如果您不认为 1 和 3 不同,那么它们可能会或可能不会转移。如果您希望排序稳定,请使用稳定的排序功能。现在你不允许 JS 对其进行正确排序,因为不同的输入会产生不同的输出。
  • @JohnnyAW 再次,Bergi 对here 的排序有一篇精彩的文章。另外,是的,Plunkr 很糟糕——你必须打开控制台才能看到输出。这很烦人。好像 JSBin 和 StackOverflow(带有 sn-ps)是唯一意识到如何正确操作的网站
【解决方案2】:

由于sort() is not necessarily stable,如果要保留在结果数组中的位置,则需要在排序前保存元素的位置,如果值相等,则将其用作比较参数。但是您的问题是,您有多个值,不能只查找起始数组中的位置。您需要将值包装在对象中:

var values= [1,2,3,4,5,6,7,8,9,2,15,3,4,5,1,2,3,4,0,2,3];
var wrappedValues = [];
//first create wrapped values
for(var i = 0;i < values.length;i++){
    wrappedValues.push({value : values[i], index : i});
}
//now sort wrapped values
wrappedValues.sort(function(a, b) {
    var result = a.value % 2 - b.value % 2;
    if(result == 0){
        return a.index - b.index;
    }
    return result;
});
//now unwrappe the values:
var unwrappedValues = [];
wrappedValues.forEach(function(entry) {
    unwrappedValues.push(entry.value);
});
console.log(unwrappedValues );

顺便说一句。您的问题的一部分在于您提供的答案的比较功能:

return a % 2 - b % 2 || a - b;

这个函数在|| a - b中升序排序

【讨论】:

  • 如果我没记错的话,那就是 decorate-sort-undecorate 模式,尽管它通常使用 .map(/* decorate */).sort().map(/* undecorate */) 来避免声明中间临时值。
  • @vlaz 但.map() 创建了一个新数组,那么如何避免声明中间临时值呢? o.O
  • 好吧,你不必声明它们。显然它们仍然存在,但您不需要在代码中关心它。您在这里需要的只是输入-> 输出,而wrappedValues 只是噪音。类似地,name unwrappedValues 也只是噪音——当它们再次以普通值的形式出现时,你真的关心这些值曾经被包裹在 something 中吗?
  • @vlaz 哦等等,你说“声明”.. nvm。我又误读了 :D 是的,你是对的,那会更短。但我仍会以这种方式保留代码,以便 OP 更容易理解。
猜你喜欢
  • 2021-05-31
  • 2016-06-23
  • 2013-07-21
  • 2020-07-08
  • 1970-01-01
  • 2021-09-15
  • 1970-01-01
  • 2017-02-06
  • 1970-01-01
相关资源
最近更新 更多