В этом руководстве вы узнаете, как использовать метод JavaScript Array sort()
для сортировки массивов чисел, строк и объектов.
Помимо возврата отсортированного массива, метод изменяет позиции элементов в исходном массиве. По умолчанию метод sort()
сортирует элементы массива в порядке возрастания, начиная с наименьшего значения и заканчивая наибольшим значением. Метод преобразует элементы в строки и сравнивает строки для определения порядка.
Рассмотрим следующий пример:
let numbers = [0, 1 , 2, 3, 10, 20, 30 ]; numbers.sort(); console.log(numbers);
Результат:
[ 0, 1, 10, 2, 20, 3, 30 ]
В этом примере метод sort()
помещает 10 перед 2, потому что строка «10» предшествует «2» при сравнении строк.
Чтобы это исправить, вам нужно передать функцию сравнения в метод sort()
. Метод будет использовать функцию сравнения для определения порядка элементов.
Синтаксис:
array.sort(comparefunction)
Метод sort()
принимает необязательный аргумент, представляющий собой функцию, которая сравнивает два элемента массива.
Если вы опустите функцию сравнения, метод sort()
сортирует элементы с порядком сортировки, основанным на значениях кодовой точки Unicode элементов, как упоминалось ранее.
Функция сравнения метода принимает два аргумента и возвращает значение, определяющее порядок сортировки. Ниже показан синтаксис функции сравнения:
function compare(a,b) { // ... }
Функция compare()
принимает два аргумента a
и b
. Метод sort()
будет сортировать элементы на основе возвращаемого значения функции compare()
по следующим правилам:
- Если
compare(a,b)
меньше нуля, методsort()
сортируетa
по более низкому индексу, чемb
. Другими словами,a
придет первым. - Если
compare(a,b)
больше нуля, метод сортируетb
по более низкому индексу, чемa
, т. е. b будет стоять первым. - Если
compare(a,b)
возвращает ноль, методsort()
считает a равным b и оставляет их позиции без изменений.
Чтобы решить проблему сортировки числа, вы можете использовать следующий синтаксис:
let numbers = [0, 1 , 2, 3, 10, 20, 30 ]; numbers.sort( function( a , b){ if(a > b) return 1; if(a < b) return -1; return 0; }); console.log(numbers);
Выход:
[ 0, 1, 2, 3, 10, 20, 30 ]
Или вы можете определить функцию сравнения, используя синтаксис стрелочной функции:
let numbers = [0, 1 , 2, 3, 10, 20, 30 ]; numbers.sort((a,b) => { if(a > b) return 1; if(a < b) return -1; return 0; }); console.log(numbers);
А следующий — самый простой, поскольку элементы массива — числа:
let numbers = [0, 1, 2, 3, 10, 20, 30]; numbers.sort((a, b) => a - b); console.log(numbers);
Сортировка массива строк
Предположим, у вас есть следующий массив строк с именами animals
:
let animals = [ 'cat', 'dog', 'elephant', 'bee', 'ant' ];
Чтобы отсортировать элементы массива animals
в порядке возрастания в алфавитном порядке, вы используете метод sort()
без передачи функции сравнения, как показано в следующем примере:
let animals = [ 'cat', 'dog', 'elephant', 'bee', 'ant' ]; animals.sort(); console.log(animals);
Выход:
[ 'ant', 'bee', 'cat', 'dog', 'elephant' ]
Чтобы отсортировать массив animals
в порядке убывания, вам нужно изменить логику функции сравнения и передать ее методу sort()
, как в следующем примере.
let animals = [ 'cat', 'dog', 'elephant', 'bee', 'ant' ]; animals.sort((a, b) => { if(a > b) return -1; if(a < b) return 1; return 0; }); console.log(animals);
Выход:
[ 'elephant', 'dog', 'cat', 'bee', 'ant' ]
Предположим, у вас есть массив, содержащий элементы как в верхнем, так и в нижнем регистре, как показано ниже:
// sorting array with mixed cases let mixedCaseAnimals = [ 'Cat', 'dog', 'Elephant', 'bee', 'ant' ];
Чтобы отсортировать этот массив по алфавиту, вам нужно использовать пользовательскую функцию сравнения, чтобы преобразовать все элементы в один и тот же регистр, например, в верхний регистр для сравнения, и передать эту функцию методу sort()
.
let mixedCaseAnimals = [ 'Cat', 'dog', 'Elephant', 'bee', 'ant' ]; mixedCaseAnimals.sort(function(a, b) { let x = a.toUpperCase(), y = b.toUpperCase(); return x == y ? 0 : x > y ? 1 : -1; });
Выход:
[ 'ant', 'bee', 'Cat', 'dog', 'Elephant' ]
Сортировка массива строк с не-ASCII-символами
Метод sort()
отлично работает со строками с символами ASCII. Однако для строк с символами, отличными от ASCII, например, é, è и т. д., метод sort()
не будет работать правильно. Например:
let animaux = ['zèbre', 'abeille', 'écureuil', 'chat']; animaux.sort(); console.log(animaux);
Как видите, строка écureuil
должна стоять перед строкой zèbre
.
Чтобы решить эту проблему, вы используете метод localeCompare()
объекта String
для сравнения строк в определенной локали, например:
animaux.sort(function(a, b) { return a.localeCompare(b); }); console.log(animaux);
Выход:
[ 'abeille', 'chat', 'écureuill', 'zèbree' ]
Элементы массива animaux
теперь расположены в правильном порядке.
Сортировка массива чисел
Предположим, у вас есть массив чисел с именем scores
, как в следующем примере.
let scores = [ 9, 80, 10, 20, 5, 70 ];
Чтобы отсортировать массив чисел, вам нужно передать пользовательскую функцию сравнения, которая сравнивает два числа.
В следующем примере массив scores
сортируется в числовом порядке в порядке возрастания.
let scores = [ 9, 80, 10, 20, 5, 70 ]; // sort numbers in ascending order scores.sort((a, b) => a - b); console.log(scores);
Выход:
[ 5, 9, 10, 20, 70, 80 ]
Чтобы отсортировать массив чисел в порядке убывания, вам просто нужно изменить логику в функции сравнения, как показано в следующем примере:
let scores = [ 9, 80, 10, 20, 5, 70 ]; // descending order scores.sort((a, b) => b - a); console.log(scores);
Выход:
[80, 70, 20, 10, 9, 5]
Сортировка массива объектов по заданному свойству
Ниже приведен массив объектов employee
, где каждый объект содержит три свойства: name
, salary
и hireDate
.
let employees = [ {name: 'John', salary: 90000, hireDate: "July 1, 2010"}, {name: 'David', salary: 75000, hireDate: "August 15, 2009"}, {name: 'Ana', salary: 80000, hireDate: "December 12, 2011"} ];
По числовому признаку
В следующем примере показано, как отсортировать сотрудников по salary
в порядке возрастания.
// sort by salary employees.sort(function(x, y) { return x.salary - y.salary; }); console.table(employees);
Выход:
Этот пример аналогичен примеру сортировки массива чисел в порядке возрастания. Разница в том, что вместо этого он сравнивает свойство salary
двух объектов.
По строковому свойству
Чтобы отсортировать массив employees
по свойству name
без учета регистра, вы передаете функцию сравнения, которая сравнивает две строки без учета регистра следующим образом:
employees.sort(function(x, y) { let a = x.name.toUpperCase(), b = y.name.toUpperCase(); return a == b ? 0 : a > b ? 1 : -1; }); console.table(employees);
По свойству даты
Предположим, вы хотите отсортировать сотрудников по дате приема на работу каждого сотрудника.
Данные о дате найма хранятся в свойстве hireDate
объекта сотрудника. Однако это всего лишь строка, представляющая допустимую дату, а не объект Date
.
Поэтому, чтобы отсортировать сотрудников по дате найма, сначала нужно создать действительный объект Date
из строки даты, а затем сравнить две даты, что равносильно сравнению двух чисел.
Вот решение:
employees.sort(function(x, y) { let a = new Date(x.hireDate), b = new Date(y.hireDate); return a - b; }); console.table(employees);
Оптимизация метода
На самом деле метод sort()
вызывает функцию сравнения несколько раз для каждого элемента массива.
Пример:
let rivers = ['Nile', 'Amazon', 'Congo', 'Mississippi', 'Rio-Grande']; rivers.sort(function(a, b) { console.log(a, b); return a.length - b.length; });
Выход:
Amazon Nile Congo Amazon Congo Amazon Congo Nile Mississippi Congo Mississippi Amazon Rio-Grande Amazon Rio-Grande Mississippi
Как это работает:
- Во-первых, объявите массив
rivers
, состоящий из известных названий рек. - Во-вторых, отсортируйте массив
rivers
по длине его элемента с помощью методаsort()
. Мы выводим элементы массиваrivers
в веб-консоль всякий раз, когда методsort()
вызывает функцию сравнения.
Как показано в выходных данных выше, каждый элемент оценивался несколько раз, например, Amazon — 4 раза, Congo — 2 раза и т. д.
Если количество элементов массива увеличивается, это может привести к снижению производительности.
Вы не можете уменьшить количество раз выполнения функции сравнения. Однако вы можете уменьшить работу, которую должно выполнять сравнение. Этот метод называется преобразованием Шварца.
Чтобы реализовать это, выполните следующие действия:
- Сначала извлеките фактические значения во временный массив с помощью метода map().
- Во-вторых, отсортируйте временный массив с уже оцененными (или преобразованными) элементами.
- В-третьих, пройдитесь по временному массиву, чтобы получить массив с правильным порядком.
Вот решение:
// temporary array holds objects with position // and length of element var lengths = rivers.map(function (e, i) { return {index: i, value: e.length }; }); // sorting the lengths array containing the lengths of // river names lengths.sort(function (a, b) { return +(a.value > b.value) || +(a.value === b.value) - 1; }); // copy element back to the array var sortedRivers = lengths.map(function (e) { return rivers[e.index]; }); console.log(sortedRivers);
Выход:
[ 'Nile', 'Congo', 'Amazon', 'Rio-Grande', 'Mississippi' ]
В этом руководстве вы узнали, как использовать метод JavaScript Array sort()
для сортировки массивов строк, чисел, дат и объектов.