简体   繁体   English

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

[英]Sorting an array of objects in Chrome

EDIT: As noted by kennytm below and after investigating myself, according to the ECMA spec , when two objects are determined to be equal in a custom sort, JavaScript is not required to leave those two objects in the same order. 编辑:正如下面kennytm和调查自己后指出,根据ECMA规范 ,当两个物体被确定为在自定义排序相同,JavaScript是不是必须离开以相同的顺序这两个对象。 Both Chrome and Opera are the only two major browsers to choose to have non-stable sorts, but others include Netscape 8&9, Kazehakaze, IceApe and a few others. Chrome和Opera是唯一两种选择不稳定排序的主要浏览器,但其他浏览器包括Netscape 8&9,Kazehakaze,IceApe和其他一些浏览器。 The Chromium team has marked this bug as "Working as intended" so it will not be "fixed". Chromium团队已将此错误标记为“按预期工作”,因此不会“修复”。 If you need your arrays to stay in their original order when values are equal, you will need to employ some additional mechanism (such as the one above). 如果您需要数组在值相等时保持其原始顺序,则需要使用一些其他机制(例如上面的那个)。 Returning 0 when sorting objects is effectively meaningless, so don't bother. 排序对象时返回0实际上没有意义,所以不要打扰。 Or use a library that supports stable sort such as Underscore/Lodash. 或者使用支持稳定排序的库,例如Underscore / Lodash。


I just got a report that some code I wrote is breaking on Chrome. 我刚刚得到一份报告,我写的一些代码在Chrome上打破了。 I've tracked it down to a custom method I'm using to sort an array of objects. 我已经将它跟踪到我用于对对象数组进行排序的自定义方法。 I am really tempted to call this a bug, but I'm not sure it is. 我真的很想把它称为一个错误,但我不确定是不是。

In all other browsers when you sort an array of objects, if two objects resolve to the same value their order in the updated array is left unchanged. 在对所有其他浏览器排序对象数组时,如果两个对象解析为相同的值,则更新数组中的顺序保持不变。 In Chrome, their order is seemingly randomized. 在Chrome中,他们的订单似乎是随机的。 Run the code below in Chrome and any other browser you want. 在Chrome和您想要的任何其他浏览器中运行以下代码。 You should see what I mean. 你应该明白我的意思。

I have two questions: 我有两个问题:

First, was I right in assuming that when your custom sorter returns 0 that the two compared items should remain in their original order (I have a feeling I was wrong). 首先,我是否正确地假设当您的自定义分拣机返回0 ,两个比较的项目保持其原始顺序(我有一种感觉我错了)。

Second, is there any good way of fixing this? 第二,有什么好方法可以解决这个问题吗? The only thing I can think of is adding an auto-incrementing number as an attribute to each member of the array before sorting, and then using that value when two items sort is comparing resolve to the same value. 我唯一能想到的是在排序之前将自动递增数字作为属性添加到数组的每个成员,然后在两个项sort时将该值与同一值进行比较时使用该值。 In other words, never return 0. 换句话说,永远不会返回0。

Here's the sample code: 这是示例代码:

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);
}

In all other browsers, what I see is that only the first member and the last member of the array get moved (I see 7,2,3,4,5,6,1 ) but in Chrome the inner numbers are seemingly randomized. 在所有其他浏览器中,我看到只有第一个成员和数组的最后一个成员被移动(我看到7,2,3,4,5,6,1 ),但在Chrome中,内部数字似乎是随机的。

[EDIT] Thank you very much to everyone who answered. [编辑]非常感谢所有回答的人。 I guess that 'inconsistent' doesn't necessary mean it's a bug. 我想“不一致”并不一定意味着它是一个错误。 Also, I just wanted to point out that my b property was just an example. 另外,我只想指出我的b属性只是一个例子。 In fact, I'm sorting some relatively wide objects on any one of about 20 keys according to user input. 事实上,我根据用户输入在大约20个键中的任何一个上排序一些相对宽的对象。 Even keeping track of what the user last sorted by still won't solve the problem of the randomness I'm seeing. 即使跟踪用户最后排序的内容仍然无法解决我看到的随机性问题。 My work-around will probably be a close variation of this (new code is highlighted): 我的解决方案可能是一个非常接近的变化(新代码突出显示):

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);}

The ECMAScript standard does not guarantee Array.sort is a stable sort . ECMAScript标准保证Array.sort是一个稳定的排序 Chrome (the V8 engine) uses in-place QuickSort internally (for arrays of size ≥ 22, else insertion sort) which is fast but not stable . Chrome(V8引擎) 在内部使用就地QuickSort (对于大小≥22的阵列,否则插入排序),这是快速但不稳定的

To fix it, make customSort compare with .b as well, eliminating the need of stability of the sorting algorithm. 要修复它, customSort.b进行比较,从而消除分类算法的稳定性。

The V8 sort is not stable, unfortunately. 不幸的是,V8排序并不稳定。 I'll see if I can dig up the Chromium bug about this. 我会看看我是否可以挖掘出关于此的Chromium bug。

V8 sort is now stable ! V8排序现在稳定了

May be you know it already but you can use an array to sort on multiple columns and avoid this bug: 可能你已经知道了但是你可以使用数组对多列进行排序并避免这个错误:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM