Какова устойчивость Array.sort () метод в различных браузерах?

Я знаю, что спецификация Сценария ECMA не указывает, какой алгоритм использовать для сортировки массивов, и при этом она не указывает, должен ли вид быть стабильным.

Я нашел эту информацию для Firefox, который указывает, что Firefox использует стабильный вид.

Кто-либо знает о IE 6/7/8, Chrome и Safari?

63
задан Jenny O'Reilly 20 October 2018 в 15:52
поделиться

3 ответа

Начиная с ES2019, sort должен быть стабильным. В ECMAScript с 1-й редакции по ES2018 допускалось, чтобы она была нестабильной.

Простой тестовый пример (игнорируйте заголовок, второй набор чисел должен быть последовательным, если сортировка движка стабильна). Примечание. Этот тестовый пример не работает для некоторых версий Chrome (технически V8), которые переключают алгоритмы сортировки в зависимости от размера массива, используя стабильную сортировку для небольших массивов, но нестабильную для больших массивов. ( Подробности .) См. Конец вопроса для модифицированной версии, которая делает массив достаточно большим для запуска поведения.

Сортировка IE была стабильной, пока я ее использовал (например, IE6). Еще раз проверяю в IE8, и, похоже, это все еще так.

И хотя на той странице Mozilla, на которую вы ссылаетесь, говорится, что сортировка Firefox стабильна, я определенно говорю, что это не всегда имело место до (и включая) Firefox 2.0.

Некоторые беглые результаты:

  • IE6 +: стабильный
  • Firefox <3: нестабильный
  • Firefox> = 3: стабильный
  • Chrome <70: нестабильный
  • Chrome> = 70: стабильный
  • Opera <10: нестабильный
  • Opera> = 10: стабильный
  • Safari 4: стабильный
  • Edge: нестабильный для длинных массивов (> 512 элементов )

Все тесты на Windows.

См. Также: Реализация алгоритма быстрой стабильной сортировки в javascript

Этот тестовый пример (измененный из здесь ) продемонстрирует проблему в V8 (например, Node v6, Chrome

 function Pair (_x, _y) {this.x = _x; this.y = _y; } функция pairSort (a, b) {return a.x - b.x; } var y = 0; var check = []; while (check.length <100) {check.push (новая пара (Math.floor (Math.random () * 3) + 1, ++ y)); } check.sort (pairSort); var min = {}; var issues = 0; for (var i = 0; i  entry.y) {console.log ("Нестабильно в" + found.i + ":" + found.y + ">" + entry.y); ++ вопросы; }} еще {мин [запись.x] = {х: запись.x, у: запись.y, я: я}; }} if (! issues) {console.log ("Сортировка стабильна"); } 
63
ответ дан 24 November 2019 в 16:27
поделиться

Я хотел бы поделиться трюком, который я обычно использую в 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;
}

В общем, стабильные алгоритмы сортировки только созревают и по-прежнему требуют больше дополнительной памяти по сравнению со старым добрым qsort. Думаю, именно поэтому очень немногие спецификации требуют стабильной сортировки.

14
ответ дан 24 November 2019 в 16:27
поделиться

Если вы ищете список браузеров, в которых следует использовать неродной алгоритм сортировки, мое предложение - не делать.

Вместо этого проверьте вменяемость сортировки при загрузке скрипта и на основании этого принимайте решение.

Поскольку спецификация не требует определенного поведения в этом отношении, она не застрахована от последующих изменений, даже в пределах одной и той же строки браузера.

Вы можете отправить патч на http://www.browserscope.org/, чтобы включить такие тесты в их набор. Но опять же, обнаружение функций превосходит обнаружение браузеров.

-2
ответ дан 24 November 2019 в 16:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: