Сортировка массива объектов в JavaScript
В этом посте мы обсудим, как сортировать массив объектов в JavaScript.
1. Использование Array.sort() метод
Собственный метод JavaScript sort() обычно используется для на месте сортировать элементы массива. sort() метод дополнительно принимает функцию сравнения, которая определяет порядок сортировки. Если x а также y два элемента сравниваются с функцией сравнения comp , то если:
- comp(x, y) < 0 , x предшествует y в отсортированном порядке.
- comp(x, y) = 0 , относительный порядок x а также y остается неизменной.
- comp(x, y) > 0 , x идет после y в отсортированном порядке.
Вы можете реализовать функцию сравнения либо с помощью функциональных выражений, либо с помощью стрелочных функций. Без функции сравнения все элементы будут преобразованы в строку, а сравнение будет производиться в лексикографическом порядке. Любые неопределенные элементы перемещаются в конец массива.
The sort() можно использовать для сортировки массива объектов по одному или нескольким их свойствам. В следующем примере кода показано использование sort() метод для сортировки массива объектов с помощью year поле.
Как делать сортировку в JavaScript при помощи sort()
![]()
В этой статье вы узнаете как делать сортировку в JavaScript при помощи метода sort() , не только обычную, как предполагает этот метод, а с задаваемыми параметрами и в самом конце вы узнаете как сортировать объекты, вложенные в массив по различным критериям.
Сортировка массивов в JavaScript делается через метод array.sort() , этот метод возможно также недооценен, как и неверно многими понимаем. Во время вызова sort() , сам по себе он сортирует массив в алфавитном порядке, но не всё так просто, если попытаться зайти дальше. Давайте более детально посмотрим на работу этого метода.
Сортировка массива в алфавитном порядке
Выполнить такую сортировку довольно просто. Просто вызовите array.sort() без любых параметров:
Обратите внимание на возрастающий порядок. Чтобы сделать его убывающим, то самым простым способом тут будет применение другого метода для массивов в комбинации с sort() — это reverse() .
А теперь, перед тем, чтобы расслабиться, посмотрите на то, что случится когда мы вызовем array.sort() на массиве из чисел:
Хотя 7 в численном порядке меньше, чем 40 или 300, в лексикографическом порядке, семёрка больше, таким образом она оказывается в правее всех в отсортированном массиве. Всегда имейте в виду, что по-дефолту array.sort() сортирует элементы в лексикографическом порядке.
Итак, мы узнали то, что нужно знать для простого использования этого метода. Но существует куда больше, связанного с ним, чем может показаться с первого взгляда. Array.sort() допускает дополнительные параметры в виде функций, которые очень сильно могут помочь в сортировке массива, основываясь на любом заданном критерии, таком как сортировке массива в числовом порядке или перемешанная сортировка.
Передаём функцию в array.sort()
Как говорилось выше, array.sort() допускает дополнительные параметры в виде функций (давайте назовем её sortfunction ). Формат такой функции будет выглядеть таким образом:
Когда такая функция передаётся в array.sort() , элементы массива сортируются, основываясь на взаимосвязи между каждой парой элементов a и b и значением, отдаваемым функцией. Есть три возможных числа, которые отдадутся функцией:<0 (меньше нуля), 0, >0 (больше нуля).
В первом случае, когда меньше нуля, a отсортируется с индексом меньшими, чем b .
При нуле: a и b будут рассматриваться как равные и сортировка производиться не будет.
Больше нуля: Сортировка b будет меньшего индекса, чем a .
То есть, для того, чтобы сортировка прошла по числам и в возрастающем порядке, функция-параметр должна быть такой:
Сортируем массив в числовом порядке
Чтобы отсортировать массив в числовом порядке, просто передайте sortfunction к array.sort() , а затем возвратите разницу между a и b , оба параметра автоматически отправятся в функцию:
Это работает так, как и должно работать, так как всякий раз когда a меньше, чем b , возвращается негативное значение, что ведет к тому, что меньший элемент всегда будет выставляться левее большего, а другими словами, порядок будет выстроен по возрастанию. Обратите внимание на то, что мы определили нашу функцию сортировки прямо внутри sort() , как анонимную, вместо того, чтобы создавать отдельную функцию и передавать ещё в sort() — оба варианта выдадут одинаковый результат.
Сортировка массива в числовом порядке, но по убывающей, отличается не многим и всего лишь требует реверса двух операндов a и b :
Делаем случайный порядок у массива
Чтобы перетасовать элементы в массиве нам нужно, чтобы sortfunction возвращал <0, 0 или >0 рандомно, независимо от того, что выдаст a и b. Вот небольшой трюк с этим делом:
Как вы видите у array.sort() есть тайные стороны. На самом деле, вы даже можете сортировать массивы, которые содержат не только примитивы, а объекты со свойствами. Давайте рассмотрим этот вариант:
Сортируем массив объектов
Сейчас мы пойдем дальше и предположим, что ваш массив содержит не только простые численные или строковые значения, а вместо них объекты со свойствами:
Массив employees — это массив, состоящий из объектов со свойствами разного типа, от строк, чисел до дат (в данном случае строка с датой). Метод sort() можно использовать для сортировки массива, основываясь на значениях одного из свойств, например сортировке по имени, возрасту и в нашем случае, даже дате выхода на пенсию. В общем, тут идея довольно простая, вам нужно изменить функцию сравнения таким образом, что она сравнивала требуемые значения свойств. Давайте посмотрим как это работает.
Сортировка по возрасту
Итак, давайте начнем сортировать наш массив employees по возрасту сотрудников в возрастающем порядке. Вот функция сравнения, которая это сделает:
С методом сортировки, указанным выше, наш массив теперь сортируется по свойству age (т.е. возраст). И таким образом, теперь у нас employee[0] это Edward, а employee[1] это George. Этот процесс очень похож на сортировку массива с числовыми значениями по возрастающей, но тут вместо вычета простого b из a , нам надо вычесть b.age из a.age , или иными словами свойство элемента, который мы хотим отсортировать.
Сортировка по имени
В наши дни сортировка по возрасту сотрудника может выглядеть довольно бесчувственной и некорректной, так что давайте отсортируем по именам сотрудников в возрастающем порядке. Вспомните, что по-дефолту, сортировка массива, который содержит примитивы, такие как строки, происходит в алфавитном порядке. Что говорит о том, что вам просто надо вызвать sort() метод, без любой функции сравнения, в общем просто myarray.sort() . Это не работает, так как данные по которым мы хотим отсортировать не являются массивом. Так что же делать? Фокус тут в том, чтобы вручную написать функцию сравнения, которая отсортирует массив по-алфавиту, что в свою очередь даст нам указать где находятся данные строк. Давайте посмотрим:
Это отсортирует массив employees по именам в возрастающем порядке, так что теперь employee[0] это Christine, employee[1] это Edward и так далее. Тут мы сравниваем две строки a.name с b.name и возвращаем -1, 1 или 0, в соответствии с сортировкой, точно определенной формулой, которую использует сам sort() , без передачи какой-либо другой функции. Как вы уже наверное выяснили, в JavaScript вы можете без сомнений сравнивать две строки.
Сортировка по дате
И наконец, предположим, что вам нужно отсортировать сотрудников по их дате выхода на пенсию. Эта информация хранится в свойстве retiredate и чтобы сделать всё интереснее, это будет не объект с датой, а просто строка. Что нам нужно сделать первым делом, так это создать валидный объект даты из строки даты выхода на пенсию, хоть впоследствии процесс и будет таким же, как и сортировка по числам:
Это отсортирует массив таким образом, что работник, выходящий на пенсию раньше всех, появится первым. employees[0] теперь будет Sarah. Это сработает, потому что JavaScript даст вам сравнить и/или сделать арифметические вычисления на объекте даты, который в первую очередь автоматически сконвертируется в числовой вид.
Sort an Array of Objects in JavaScript
Suppose you have a JavaScript array containing Star Trek: The Next Generation characters:
How do you sort this array by different properties?
Sorting By age
JavaScript's built-in Array#sort() function optionally takes a callback parameter that compares two elements in the array.
The callback function is called compareFunction() . If compareFunction(a, b) returns a value that is < 0 , JavaScript considers a to be less than b . And if compareFunction(a, b) returns a value that is > 0 , JavaScript considers b to be greater than a .
That means it is easy to sort by a numeric property like age . If a.age — b.age < 0 , that means b is older than a .
Sorting by lastName
Sorting by a string property like lastName is also easy, because JavaScript's < and > properties can handle strings. To sort by a string property, your compareFunction() can compare the two strings using < :
Sorting by rank
Sorting by rank is a bit trickier because rank isn't necessarily in alphabetical order. JavaScript doesn't know that 'Captain' is a higher rank than 'Lieutenant'.
To sort by a custom ordering, you should define a map from rank to a numeric value to make for easier comparison.
Несколько полезных кейсов при работе с массивами в JavaScript
Очень часто на тостере вижу вопросы вида «Как отсортировать массив в JavaScript по определенному правилу?», «Как сделать с массивом в JavaScript <действие>?» и т.д.
Под катом собраны некоторые манипуляции над массивами.
Преобразование массиво-подобного объекта в массив
В es2015 была добавлена замечательная функция Array.from, которая умеет преобразовывать в массив все, что похоже на массив. Принцип ее работы следующий:
- Если в передаваемом объекте в свойстве [Symbol.iterator] есть функция, она будет использована как генератор для наполнения массива
- Если в передаваемом объекте есть свойство length, то массив будет составлен из целочисленных индексов объекта от 0 до (object.length — 1)
- В других случаях она вернет пустой массив
Сумма и произведение массива
Но с суммой нужно быть аккуратнее, если в массиве встретится не числовое значение, то оно будет преобразовано в строку, и начиная с него пойдет конкатенация строк, чтобы этого избежать можно использовать более безопасный вариант:
Поиск в массиве и фильтрация массива
Многие знают о таком замечательном методе как indexOf, который ищет в массиве переданное в первом аргументе значение по точному соответствию (value === element) и возвращает индекс первого совпадения или -1 если ничего не найдено. Так же вторым аргументом можно передать индекс, с которого нужно начать поиск.
Есть похожий на него метод lastIndexOf, работающий аналогично, только поиск производится с конца массива. Но бывают ситуации, когда поиск по точному соответствию не подходит, для этих случаев существуют методы find и findIndex работают они похожим образом, вызывая для каждого элемента функцию, переданную в первом аргументе с параметрами (element, index, array). Поиск осуществляется до тех пор, пока функция не вернет true. find возвращает сам найденный элемент или undefined если ничего не найдено, а findIndex его индекс или -1 соответственно.
Пример, найдем в массиве первый элемент, который больше 5:
Еще одна частая задача, это фильтрация массива. Для этих целей существует метод filter, который возвращает новый массив, состоящий только из тех элементов, для которых функция переданная в первом аргументе вернула true:
Так же иногда бывает нужно просто проверить элементы массива на соответствие некоторому условию, для этого существуют методы some и every, как и предыдущие методы они работают с функцией переданной в первом аргументе:
some возвращает true, если хотя бы для одного аргумента функция вернула true, и false в противном случае
every возвращает false, если хотя бы для одного аргумента функция вернула false, и true в противном случае
Обе останавливают поиск, когда искомое значение найдено. Это можно использовать несколько нестандартно, как известно метод forEach перебирает все элементы массива, но его работу невозможно прервать, однако это становится возможным благодаря методу some:
Сортировка массивов
Для сортировки массива используется метод sort. По умолчанию все элементы сортируются как строки по возрастанию кодов utf-16. Стандартное поведение можно изменить передав первым аргументом функцию-компаратор. Компаратор — это такая функция, которая получает на вход два аргумента (a, b) и должна вернуть: -1, если a идет раньше чем b; 1, если a идет позже чем b; 0, если порядок не важен, то есть аргументы равны. Метод sort довольно лоялен к компаратору и принимает на выходе любые значения меньше 0 как -1, а значения больше 0 как 1.
Важно! Метод sort, хотя и возвращает результат, все операции проводит над исходным массивом. Если необходимо оставить исходный массив без изменений, можно воспользоваться следующим приемом:
Так как метод slice без аргументов возвращает клон массива, метод sort будет работать с этим клоном и в результате его вернет.
Простая сортировка, сравнение элементов как числа
Типобезопасная сортировка
Сортировка массива объектов по их свойствам
Более частая ситуация возникает, когда нужно отсортировать массив однотипных объектов по их свойству, а то и нескольким свойствам сразу, для этого удобно иметь функцию, которая создавала бы нам компаратор на любой случай жизни:
Сортировка подсчетом
Хотя метод sort работает достаточно быстро, на очень больших массивах его скорости может оказаться недостаточно, благо есть метод сортировки который показывает большую производительность при соблюдении 2х условий, а именно — массив достаточно большой (больше 100.000 элементов) и в массиве много повторяющихся значений. Называется он сортировкой подсчетом. Я представлю пример его реализации для сортировки по возрастанию массива из числовых элементов: