Вот следующая часть моей серии постов о вопросах, заданных мне в моем фиктивном интервью по JavaScript.
Когда меня попросили отсортировать элементы массива чисел, я сначала сделал ошибку, просто воспользовавшись методом sort(). Хотя это прекрасно работает со строковыми элементами, с числами получается несколько странный результат. Давайте посмотрим, что происходит.
Во-первых, массив строк.
const anArray = [“today”, “is”, “a”, “whole”, “new”, “beginning”] console.log(anArray.sort()) [“a”, “beginning”, “is”, “new”, “today”, “whole”]
Элементы в anArray сортируются в алфавитном порядке по первой букве. Достаточно просто. Если бы два или более элемента начинались с одной и той же буквы, метод сортировки перешел бы ко второй букве и так далее. Например:
const newArray = [“cat”, “car”, “bat”, “box”, “doll”, “dill”] console.log(newArray.sort()) [“bat”, “box”, “car”, “cat”, “dill”, “doll”]
А если мы используем sort() для массива чисел?
const numArray = [12, 5, 13, 9, 2, 0] console.log(numArray.sort()) [0, 12, 13, 2, 5, 9]
Подожди. Как 12 и 13 могут предшествовать 2, 5 и 9???
Это происходит потому, что использование sort() преобразует элементы массива в строки, а затем размещает их в порядке Unicode.
Мой интервьюер помог, намекнув на использование функции для сравнения этих числовых элементов. Напрягая память, я использовал в скобках sort() следующее:
function(a, b){return a — b}
Давайте попробуем отсортировать numArray с помощью этого.
console.log(numArray.sort(function(a, b){return a — b})) [0, 2, 5, 9, 12, 13]
Это больше походит на это. Теперь у нас есть элементы массива, отсортированные в порядке возрастания (то есть от меньшего к большему). А что, если мы хотим отсортировать их по убыванию (от большего к меньшему)? Вместо вычитания b из a в операторе return мы вычитаем a из b.
console.log(numArray.sort(function(a, b){return b — a})) [13, 12, 9, 5, 2, 0]
Как это все работает? Функция сравнения принимает два значения (представленные параметрами a и b), вычитает одно из другого и возвращает значение методу сортировки. Если a — b возвращает отрицательное значение, метод sort установит для a более низкий индекс в массиве, чем b. Используя наш пример numArray, предположим, что a равно 2, а b равно 5. Функция сравнения возьмет эти два значения и выполнит некоторые простые арифметические действия ( 2–5 = -3) и вернуть результат методу сортировки. Метод sort, получив отрицательное значение, даст 2 более низкий индекс, чем 5, поэтому при сортировке элементов в массиве в порядке возрастания 2 будет стоять перед 5.
Однако что, если a — b возвращает положительное значение? В этом случае a будет присвоен более высокий индекс. В нашем примере numArray, когда функция сравнения сравнивает 9 и 5 (9–5 = 4), она возвращает положительное значение методу сортировки, который присваивает 9 более высокий индекс. Таким образом, 9 идет после 5, когда перечисляются отсортированные элементы массива.
Это переворачивается, когда элементы массива должны быть отсортированы в порядке убывания. То есть, если b — a возвращает отрицательное значение, b присваивается более высокий индекс, а если b — a возвращает положительное значение, bприсваивается нижний индекс. Например, если b равно 2, а a равно 5, функция сравнения выполнит свой расчет (2–5 = -3), который предложит методу сортировки дать 2 имеет более высокий индекс, чем 5. Таким образом, когда перечисляются отсортированные числа, 5 будет стоять перед 2.
Но что, если функция сравнения возвращает 0? Давайте попробуем это с другим массивом чисел:
const myNumbers = [7, 5, 91, 52, 7, 8] console.log(myNumbers.sort(function(a, b){return a — b})) [5, 7, 7, 8, 52, 91]
Массив содержит две семерки, и, конечно же, когда функция сравнения доберется до их сравнения, она вернет 0 (7–7 = 0). Как говорит Mozilla Developer Network, это оставит a и b неизменными по отношению друг к другу, но отсортирует их по всем различным элементам.
Короче говоря, я настоятельно рекомендую запомнить эти две функции сравнения.
- Для сортировки по возрастанию: function(a, b){return a — b})
- Для сортировки по убыванию: function(a, b){return b — a})
И, кстати, их можно легко переписать в виде стрелочных функций:
- (a, b) => a — b
- (a, b) => b — a