Править: Как отмечено kennytm ниже и после исследования меня, согласно спецификации ECMA, когда два объекта полны решимости быть равными по пользовательскому виду, JavaScript не требуется, чтобы оставлять те два объекта в том же порядке. И Chrome и Opera являются только двумя главными браузерами, чтобы принять решение иметь нестабильные виды, но другие включают Netscape 8&9, Kazehakaze, IceApe и немногие другие. Команда Хрома отметила эту ошибку как "Работающий, как предназначено", таким образом, она не будет "зафиксирована". При необходимости в массивах для пребывания в их первоначальном заказе, когда значения будут равны, необходимо будет использовать некоторый дополнительный механизм (такой как тот выше). Возврат 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 по-видимому рандомизируются внутренние числа.
[РЕДАКТИРОВАНИЕ] Искренне благодарит Вас всем, кто ответил. Я предполагаю, что 'непоследовательный' не делает необходимый средний, это - ошибка. Кроме того, я просто хотел указать что мой 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);}
Сорт V8, к сожалению, не стабилен. Попробую откопать ошибку в Хроме по этому поводу.
Сортировка V8 теперь стабильна!
Стандарт ECMAScript не гарантирует, что Array.sort
является стабильной сортировкой . Chrome (движок V8) использует внутреннюю на месте QuickSort (для массивов размером ≥ 22, иначе сортировка вставкой), которая работает быстро, но нестабильно .
Чтобы исправить это, сравните customSort
с .b
, исключив необходимость стабильности алгоритма сортировки.
Возможно, вы это уже знаете, но вы можете использовать массив для сортировки по нескольким столбцам и избежать этой ошибки:
var customSort = function(a,b) {
return [a.a, a.b] > [b.a, b.b] ? 1:-1;
}