Какова стабильность метода Array.sort() в разных браузерах?
Я знаю, что спецификация скрипта ECMA не определяет, какой алгоритм использовать для сортировки массивов, а также не указывает, должна ли сортировка быть стабильной.
Я нашел эту информацию для Firefox, которая указывает, что Firefox использует стабильную сортировку.
Кто-нибудь знает про IE 6/7/8, Chrome и Safari?
5 ответов
Простой тестовый пример (игнорируйте заголовок, второй набор чисел должен быть последовательным, если сортировка двигателя стабильна).
Сортировка IE была стабильной до тех пор, пока я ее использовал (то есть IE6). Повторная проверка в IE8, и, похоже, все еще так.
И хотя эта страница Mozilla, на которую вы ссылаетесь, говорит о том, что сортировка Firefox стабильна, я определенно говорю, что это было не всегда до (и в том числе) до Firefox 2.0.
Некоторые краткие результаты:
- IE6 +: стабильный
- Firefox < 3: нестабильный
- Firefox >= 3: стабильный
- Хром < 70: нестабильно
- Chrome >= 70: стабильный
- Опера < 10: нестабильно
- Опера>= 10: стабильный
- Safari 4: стабильный
- Край: нестабильный для длинных массивов
Все тесты на Windows.
Смотрите также: Быстрая стабильная реализация алгоритма сортировки в javascript
Я хотел бы поделиться трюком, который я обычно использую в C/C++ для qsort()
,
JS' sort() позволяет указать функцию сравнения. Создайте второй массив такой же длины и заполните его возрастающими числами от 0.
function stableSorted(array, compareFunction) {
compareFunction = compareFunction || defaultCompare;
var indicies = new Array(array.length);
for (var i = 0; i < indicies.length; i++)
indicies[i] = i;
Это индексы в исходный массив. Мы собираемся отсортировать второй массив. Сделайте пользовательскую функцию сравнения.
indicies.sort(function(a, b)) {
Он получит два элемента из второго массива: используйте их как индексы в исходных массивах и сравните элементы.
var aValue = array[a], bValue = array[b];
var order = compareFunction(a, b);
if (order != 0)
return order;
Если элементы оказываются равными, сравните их индексы, чтобы сделать порядок стабильным.
if (a < b)
return -1;
else
return 1;
});
После sort () второй массив будет содержать индексы, которые можно использовать для доступа к элементам исходного массива в устойчивом порядке сортировки.
var sorted = new Array(array.length);
for (var i = 0; i < sorted.length; i++)
sorted[i] = array[indicies[i]];
return sorted;
}
// The default comparison logic used by Array.sort(), if compareFunction is not provided:
function defaultCompare(a, b) {
a = String(a);
b = String(b);
if (a < b) return -1;
else if (a > b) return 1;
else return 0;
}
В общем, алгоритмы стабильной сортировки только созревают и все еще требуют больше дополнительной памяти по сравнению с хорошей версией. Я думаю, именно поэтому очень немногие спецификации требуют стабильной сортировки.
Начиная с V8 v7.0 и Chrome 70, наши Array.prototype.sort
реализация сейчас стабильна.
Ранее V8 использовал нестабильную QuickSort для массивов с более чем 10 элементами. Теперь V8 использует стабильный алгоритм TimSort.
Единственный основной движок JavaScript, который до сих пор работает нестабильно Array#sort
реализация чакры, как используется в Microsoft Edge. Чакра использует QuickSort для массивов с более чем 512 элементами. Для небольших массивов используется стабильная реализация сортировки вставками.
В случае, если кто-то найдет это полезным, у меня был полифилл для этого, который я сейчас удаляю:
Если вы ищете список браузеров, в которых вы должны использовать не родной алгоритм сортировки, я советую не делать этого.
Вместо этого сделайте проверку работоспособности сортировки при загрузке скрипта и примите решение.
Поскольку спецификация не требует определенного поведения в этом отношении, она не защищена от последующих изменений, даже в пределах одной строки браузера.
Вы можете отправить патч на http://www.browserscope.org/ чтобы включить такие тесты в свой комплект. Но опять же, функция обнаружения превосходит обнаружение браузера.