Вот следующая часть моей серии постов о вопросах, заданных мне в моем фиктивном интервью по 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