在Chrome中对对象数组进行排序

And*_*rew 21 javascript sorting google-chrome

编辑:正如下面kennytm和调查自己后指出,根据ECMA规范,当两个物体被确定为在自定义排序相同,JavaScript是不是必须离开以相同的顺序这两个对象.Chrome和Opera是唯一两种选择不稳定排序的主要浏览器,但其他浏览器包括Netscape 8&9,Kazehakaze,IceApe和其他一些浏览器.Chromium团队已将此错误标记为"按预期工作",因此不会"修复".如果您需要数组在值相等时保持其原始顺序,则需要使用一些其他机制(例如上面的那个).0排序对象时返回实际上是没有意义的,所以不要打扰.


我刚刚得到一份报告,我写的一些代码在Chrome上打破了.我已经将它跟踪到我用于对对象数组进行排序的自定义方法.我真的很想把它称为一个错误,但我不确定是不是.

在对所有其他浏览器排序对象数组时,如果两个对象解析为相同的值,则更新后的数组中的顺序保持不变.在Chrome中,他们的订单似乎是随机的.在Chrome和您想要的任何其他浏览器中运行以下代码.你应该明白我的意思.

我有两个问题:

首先,我是否正确地假设当您的自定义分拣机返回时0,两个比较的项目保持其原始顺序(我有一种感觉我错了).

第二,有什么好方法可以解决这个问题吗?我唯一能想到的是在排序之前将自动递增数字作为属性添加到数组的每个成员,然后在两个项目sort将resolve与同一值进行比较时使用该值.换句话说,永远不会返回0.

这是示例代码:

var x = [
{'a':2,'b':1},
{'a':1,'b':2},
{'a':1,'b':3},
{'a':1,'b':4},
{'a':1,'b':5},
{'a':1,'b':6},
{'a':0,'b':7},
]

var customSort = function(a,b) {
    if (a.a === b.a) return 0;
    if (a.a > b.a) return 1;
    return -1;
};

console.log("before sorting");
for (var i = 0; i < x.length; i++) {
    console.log(x[i].b);
}
x.sort(customSort);

console.log("after sorting");
for (var i = 0; i < x.length; i++) {
    console.log(x[i].b);
}
Run Code Online (Sandbox Code Playgroud)

在所有其他浏览器中,我看到的是只有第一个成员和数组的最后一个成员被移动(我看到7,2,3,4,5,6,1),但在Chrome中,内部数字似乎是随机的.

[编辑]非常感谢所有回答的人.我想"不一致"并不一定意味着它是一个错误.另外,我只想指出我的b财产只是一个例子.事实上,我根据用户输入在大约20个键中的任何一个上排序一些相对宽的对象.即使跟踪用户最后排序的内容仍然无法解决我看到的随机性问题.我的解决方案可能是一个非常接近的变化(新代码突出显示):

var x = [
{'a':2,'b':1},
{'a':1,'b':2},
{'a':1,'b':3},
{'a':1,'b':4},
{'a':1,'b':5},
{'a':1,'b':6},
{'a':0,'b':7},
];
var i;

var customSort = function(a,b) {
    if (a.a === b.a) return a.customSortKey > b.customSortKey ? 1 : -1; /*NEW CODE*/
    if (a.a > b.a) return 1;
    return -1;
};

console.log("before sorting");
for (i = 0; i < x.length; i++) {console.log(x[i].b);}

for (i = 0; i < x.length; i++) {                      /*NEW CODE*/
    x[i].customSortKey = i;                           /*NEW CODE*/
}                                                     /*NEW CODE*/
x.sort(customSort);

console.log("after sorting");
for (i = 0; i < x.length; i++) {console.log(x[i].b);}
Run Code Online (Sandbox Code Playgroud)

ken*_*ytm 22

ECMAScript标准保证Array.sort是稳定的排序.Chrome(V8引擎)在内部使用就地QuickSort(对于大小≥22的阵列,否则插入排序),这是快速但不稳定的.

要修复它,也要customSort进行比较.b,无需分类算法的稳定性.


law*_*sea 8

不幸的是,V8排序并不稳定.我会看看我是否可以挖掘出关于此的Chromium bug.

  • [V8问题90:V8不稳定排序](http://code.google.com/p/v8/issues/detail?id=90"V8错误90") (6认同)

Mic*_*Mic 8

可能你已经知道了但是你可以使用数组对多列进行排序并避免这个错误:

var customSort = function(a,b) {
    return [a.a, a.b] > [b.a, b.b] ? 1:-1;
}
Run Code Online (Sandbox Code Playgroud)