РЕДАКТИРОВАНИЕ: Как отмечалось ниже, и после изучения себя, согласно спецификация ECMA, когда определяются два объекта чтобы быть равным в пользовательском порядке, JavaScript должен не, чтобы оставить эти два объекта в одном порядке. Как Chrome, так и Opera являются единственными двумя основными браузерами, которые предпочитают иметь нестабильные сорта, но другие включают Netscape 8 и 9, Kazehakaze, IceApe и некоторые другие. Команда Chromium отметила эту ошибку как "Работа по назначению", поэтому она не будет "исправлена". Если вам нужны ваши массивы, чтобы оставаться в исходном порядке, когда значения равны, вам нужно будет использовать дополнительный механизм (например, тот, который указан выше). Возвращение 0
при сортировке объектов фактически бессмысленно, поэтому не беспокойтесь. Или используйте библиотеку, поддерживающую стабильную сортировку, такую как Underscore/Lodash.
Я только что получил сообщение о том, что какой-то код, который я написал, ломается в Chrome. Я отследил его до пользовательского метода, который я использую для сортировки массива объектов. Я действительно испытываю искушение называть это ошибкой, но я не уверен, что это так.
Во всех других браузерах при сортировке массива объектов, если два объекта разрешены на одно и то же значение, их порядок в обновленном массиве остается неизменным. В Chrome их порядок, по-видимому, рандомизирован. Выполните код ниже в Chrome и любом другом браузере. Вы должны понять, что я имею в виду.
У меня есть два вопроса:
Во-первых, был ли я прав, предполагая, что когда ваш пользовательский сортировщик возвращает 0
, что два сравниваемых элемента должны оставаться в исходном порядке (у меня такое чувство, что я был неправ).
Во-вторых, есть ли хороший способ исправить это? Единственное, о чем я могу думать, это добавить автоматически увеличивающееся число как атрибут для каждого члена массива перед сортировкой, а затем использовать это значение, когда два элемента sort
сравниваются с тем же значением. Другими словами, никогда не возвращайте 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);
}
Во всех других браузерах я вижу, что только первый член и последний член массива перемещаются (я вижу 7,2,3,4,5,6,1
), но в Chrome внутренние числа кажутся рандомизированными.
[EDIT] Большое спасибо всем, кто ответил. Я думаю, что "непоследовательный" не нужен, значит, это ошибка. Кроме того, я просто хотел указать, что мое свойство 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);}