Я хочу отсортировать массив из примерно 200-300 объектов, сортируя по определенному ключу и заданному порядку (asc / desc). Порядок результатов должен быть последовательным и стабильным.
Какой алгоритм лучше всего использовать, и не могли бы вы привести пример его реализации в javascript?
Спасибо!
javascript
algorithm
sorting
Уильям Касарин
источник
источник
Ответы:
Можно получить стабильную сортировку из нестабильной функции сортировки.
Перед сортировкой вы получите расположение всех элементов. В вашем условии сортировки, если оба элемента равны, вы сортируете по позиции.
Тада! У вас стабильный сорт.
Я написал статью об этом в своем блоге, если вы хотите узнать больше об этой технике и о том, как ее реализовать: http://blog.vjeux.com/2010/javascript/javascript-sorting-table.html
источник
Поскольку вы ищете что-то стабильное, подойдет сортировка слиянием.
http://www.stoimen.com/blog/2010/07/02/friday-algorithms-javascript-merge-sort/
Код можно найти на указанном выше веб-сайте:
РЕДАКТИРОВАТЬ:
Согласно этому сообщению , похоже, что Array.Sort в некоторых реализациях использует сортировку слиянием.
источник
Array#shift
может работать за O (n) раз, а значит,merge
за O (n * n).Несколько более короткая версия того же самого с использованием функций ES2017, таких как стрелочные функции и деструктуризация:
Функция
Он принимает входной массив и функцию сравнения:
Он также возвращает новый массив вместо того, чтобы выполнять сортировку на месте, как встроенная функция Array.sort () .
Тест
Если взять следующий
input
массив, изначально отсортированный поweight
:Затем отсортируйте его,
height
используяstableSort
:Результаты в:
Однако сортировка того же
input
массива с использованием встроенногоArray.sort()
(в Chrome / NodeJS):Возврат:
Ресурсы
Обновить
источник
stableSort
Функция действительно отличное решение!Я знаю, что в течение некоторого времени на этот вопрос был дан ответ, но у меня есть хорошая стабильная реализация сортировки слиянием для Array и jQuery в моем буфере обмена, поэтому я поделюсь ею в надежде, что некоторые будущие поисковики могут найти ее полезной.
Это позволяет вам указать вашу собственную функцию сравнения, как в обычной
Array.sort
реализации.Реализация
Пример использования
источник
array.sort
, см. Здесь тест как для строк, так и для целых чисел -> jsfiddle.net/QC64jmergeSort
и не используетсяsort
, поэтому она не предназначена для замены. Иногда вам просто нужна стабильная сортировка слиянием, например, при сортировке таблиц по столбцам.Вы можете использовать следующий полифилл для реализации стабильной сортировки независимо от собственной реализации на основе утверждения, сделанного в этом ответе :
Выполненные выше тесты производительности
stableSort()
работают примерно на 57% от скорости вsort()
Chrome версии 59-61.Использование
.bind(compareFunction)
обернутой анонимной функции внутриstableSort()
повысило относительную производительность примерно с 38% за счет исключения ненужных ссылок на область видимостиcompareFunction
при каждом вызове, назначив ее вместо этого контексту.Обновить
Изменен тернарный оператор на логическое короткое замыкание, которое в среднем работает лучше (похоже, разница в эффективности составляет 2-3%).
источник
Следующий код сортирует предоставленный массив, применяя предоставленную функцию сравнения, возвращая исходное сравнение индексов, когда функция сравнения возвращает 0:
В приведенном ниже примере массив имен сортируется по фамилии, сохраняя порядок равных фамилий:
источник
jQuery.expando.split( "" ).sort( ( a, b ) => 0 ).join( "" ) === jQuery.expando
Вот стабильная реализация. Он работает с использованием собственной сортировки, но в случаях, когда элементы сравниваются как равные, вы разрываете связи, используя исходную позицию индекса.
неполный тест
другой ответ ссылался на это, но не отправлял код.
но, его не быстро , по моему эталону . Я изменил сортировку слиянием impl, чтобы принимать пользовательскую функцию компаратора, и это было намного быстрее.
источник
Вы также можете использовать Timsort. Это действительно сложный алгоритм (более 400 строк, поэтому здесь нет исходного кода), поэтому см . Описание Википедии или используйте одну из существующих реализаций JavaScript:
Реализация GPL 3 . Упакован как Array.prototype.timort. Похоже, это точная переработка кода Java.
Реализация в общественном достоянии В качестве учебного пособия пример кода показывает его использование только с целыми числами.
Timsort - это высокооптимизированный гибрид сортировки слиянием и сортировки в случайном порядке и алгоритм сортировки по умолчанию в Python и Java (1.7+). Это сложный алгоритм, поскольку он использует разные алгоритмы для многих частных случаев. Но в результате он очень быстр в самых разных обстоятельствах.
источник
Простой mergeSort из http://www.stoimen.com/blog/2010/07/02/friday-algorithms-javascript-merge-sort/
источник
Мне нужно отсортировать многомерные массивы по произвольному столбцу, а затем по другому. Я использую эту функцию для сортировки:
Обратите внимание, что ary.sort никогда не возвращает ноль, поэтому некоторые реализации функции "sort" принимают решения, которые могут быть неправильными.
Это тоже чертовски быстро.
источник
Вот как можно расширить объект Array JS по умолчанию с помощью метода-прототипа, использующего MERGE SORT . Этот метод позволяет выполнять сортировку по определенному ключу (первый параметр) и заданному порядку («asc» / «desc» в качестве второго параметра)
Вы можете проверить это сами, перетащив приведенный выше фрагмент в консоль браузера, а затем попробовав:
Или заказать на основе определенного поля в массиве объектов:
источник
Поэтому мне нужна была стабильная версия для моего приложения React + Redux, и ответ Vjeux здесь мне помог. Однако мое (общее) решение кажется отличным от других, которые я видел здесь, поэтому я поделюсь им на случай, если у кого-то еще есть подходящий вариант использования:
sort()
API, где я могу передать функцию компаратора.Мое решение - создать типизированный массив
indices
, а затем использовать функцию сравнения для сортировки этих индексов на основе массива, подлежащего сортировке. Затем мы можем использовать сортировкуindices
для сортировки исходного массива или создания отсортированной копии за один проход. Если это сбивает с толку, подумайте об этом так: где вы обычно передаете функцию сравнения, например:Вместо этого вы используете:
Скорость хорошая; в основном это встроенный алгоритм сортировки, плюс два линейных прохода в конце и один дополнительный уровень накладных расходов на косвенное указание.
Рад получить отзывы об этом подходе. Вот моя полная реализация:
источник
Я знаю, что на это было много ответов. Я просто хотел написать быструю реализацию TS для всех, кто пришел сюда в поисках этого.
Этот метод больше не работает на месте, в отличие от собственной сортировки. Также хочу отметить, что он не самый эффективный. Он добавляет две петли порядка O (n). хотя сама сортировка, скорее всего, O (n log (n)), поэтому она меньше этого.
Некоторые из упомянутых решений более производительны, подумал, что это может быть меньше кода, также используя внутренние
Array.prototype.sort
.(Для решения Javascript просто удалите все типы)
источник
Согласно v8 девблоге и caniuse.com
Array.sort
уже стабильно в соответствии с требованиями спецификации в современных браузерах, так что вам не нужно свернуть собственное решение. Единственное исключение, которое я вижу, - это Edge, который скоро должен перейти на хром и поддерживать его.источник
источник
Сортировка с подсчетом выполняется быстрее, чем сортировка слиянием (она выполняется за время O (n)), и предназначена для использования с целыми числами.
Пример:
источник
array [3, 1, 3]
хеши в[undefined, 1, undefined, 3]
. Мы получаем два неопределенных значения, в то время как алгоритм ожидает, что их будет три.