31 Js Array Functions Sort Filter Map Reduce Some Every

Массивы и методы для работы с ними: sort, filter, map, reduce, some, every … #

Мы уже рассматривали некоторые, базовые методы для работы с массивами при знакомстве с самими массивами в JavaScript. Настало время изучить ещё несколько очень полезных методов.

Это будет длинная статья. Изначально под каждый метод я хотел сделать отдельную статью, так как это сделано например на MDN.

Но при написании я понял, что у всех методов массива, которые я хотел рассмотреть есть как минимум две общие черты:

  1. Все методы с удовольствием используют колбэки и соответственно стрелочные функции.
  2. Если разобраться хотя бы с одним методом, то каждый следующий даётся намного легче.

И некоторая сложность в их понимании возникает скорее у тех, кто по-настоящему не подружился со стрелочными функциями.

Потому для начала убеждаемся, что мы знаем базу - стрелочные функции.

Это статья является базовой в объяснении работы методов массивов. И не заменяет собой документацию. Ссылки на документацию вы найдёте в конце статьи.

Сортировка массива - sort #

Javascript несёт с собой функцию сортировки. Давайте посмотрим её на примере:

let array1 = [2,3,4,5,7,1,6];
console.log(array1.sort()); // [  1, 2, 3, 4,  5, 6, 7]

Результат работы метода соответствует моим ожиданиям, правда надо помнить, что метод меняет массив и к оригинальному массиву уже не вернуться. Давайте теперь отсортируем города:

let array2 = ["Могилёв","Минск","Москва","Мухино","Муром"];
console.log(array2.sort()); // [ 'Минск', 'Могилёв', 'Москва', 'Муром', 'Мухино' ]

С городами вроде тоже всё хорошо. Может показаться, что метод sort() идеальный метод. Давайте попробуем немного более длинный ряд.

let array3 = [11, 31, 4, 5, 7, 6, 1, 3, 44, 115];
console.log(array3.sort()); 
// [  1, 11, 115, 3, 31, 4, 44, 5, 6, 7]

1, 11 и 115 идут раньше чем три и тридцать один. Сортировка, которую применяет метод sort() является лексикографической. Это значит, что он сортирует по алфавиту. Для него 1 и 11 примерно то же самое, что и “а”, и “аа”. Именно так кстати в некоторых операционных системах сортируют папки. То есть если “Аахен” идёт перед “Арканзасом”, то и “111” идёт перед “22”.

Все символы собраны в “условной” таблице символов. Сегодня это скорее всего юникод. Подробнее почитать можно об этом здесь.

Прежде чем мы научимся сортировать не по алфавиту, а на больше меньше, нам надо понять, что такое больше меньше.

Больше меньше #

И так мы должны написать функцию, которая сравнивая два числа скажет системе, что одно из них больше, а другое меньше.

Давайте начнём, сравнение по-английски compare и наш метод должен принять два числа. Если первое больше, то мы отдадим положительное число, если меньше отрицательное, а если числа равны, то отдадим ноль.

function compare(a, b) {
  if (a > b) {
    return 1;
  } else if (a < b) {
    return -1;
  } else {
    return 0;
  }
}

Вроде получилось, только нам не обязательно отдавать один и минус один, достаточно просто любое число. И если мы задумаемся, то выясним, что если а больше б, то их разница будет положительной. Если а равно б, то их разница равна нулю. А если а меньше б, то их разница равна отрицательному числу.

Нам всегда надо отдавать разницу, так вернём её сразу.

function compare(a, b) {
    return a-b;
}

Теперь мы можем передать этот способ сравнения в функцию sort(). И всё вместе будет выглядеть:

let array = [11, 31, 4, 5, 7, 6, 1, 3, 44, 115];

function compare(a, b) {
return a - b;
}

array.sort(compare);
console.log(array);

Саму функцию компаре мы конечно же можем переписать как стрелочную функцию и тогда нас кстати меньше смущает отсутствие скобок при передаче её как параметр.

let array = [11, 31, 4, 5, 7, 6, 1, 3, 44, 115];

let compare = (a, b) => a - b;

array.sort(compare);
console.log(array);

Или даже сразу записать стрелочную функцию как параметр метода sort:

let array = [11, 31, 4, 5, 7, 6, 1, 3, 44, 115];
array.sort((a, b) => a - b);
console.log(array); 

Вот так шаг за шагом мы разобрали ещё один пример использования стрелочной функции, узнали новое слово “лексикографический”, научились сортировать.

Стоит добавить, что стрелочные функции появились в JS s ES6. В ES5 это выглядело ещщё вот так:

// ES5
let array = [11, 31, 4, 5, 7, 6, 1, 3, 44, 115];
array.sort(function (a, b) {
  return a - b;
});
console.log(array);  // [ 1,  3,  4,  5,   6,  7, 11, 31, 44, 115]

Помимо более короткой записи у стрелочной функции другой подход к работе со значением this. Но это отдельная тема.

Фильтрация массива - filter #

Первое и самое важное - метод filter возвращает (или создаёт) новый массив. А значит нам нужна переменная, что бы сохранить его. Дайте возьмём список городов и найдём все города в которых больше шести букв.

let cities = ["Могилёв", "Минск", "Москва", "Мухино", "Муром", "Мюнхен", "Мурманск"];
let result = cities.filter(city => city.length > 6);
console.log(result); 
//[ 'Могилёв', 'Мурманск' ]

Мы фильтруем массив cities и говорим: “Отфильтруй, пожалуйста, все города, длина которых больше шести”.

То что мы написали вверху, по аналогии с методом сорт можно было бы записать и так:

let cities = ["Могилёв", "Минск", "Москва", "Мухино", "Муром", "Мюнхен", "Мурманск"];
let result = cities.filter(ruleFilter);
function ruleFilter(city) {
  return city.length > 6;
}
console.log(result);
//[ 'Могилёв', 'Мурманск' ]

Мне кажется, что постепенно более лаконичная запись должна начать нравиться и вам. Давайте закрепим материал и отсортируем в массиве чисел нужные нам. И это будут все между 5 и 50.

let array = [11, 31, 4, 5, 7, 6, 1, 3, 44, 115];
let luckyNumbers = array.filter((number) => number > 5 && number < 50);
console.log(luckyNumbers);
// [ 11, 31, 7, 6, 44 ]

Трансформация массива - метод map #

Давайте возведём все числа массива во вторую степень:

let array = [11, 31, 4, 5, 7, 6, 1, 3, 44, 115];
let luckyNumbers = array.map((number) => number ** 2);
console.log(luckyNumbers);
// [121, 961, 16, 25, 49, 36, 1, 9, 1936, 13225]

Или примем массив городов, а вернём количество символов в названии каждого города:

let cities = ["Могилёв", "Минск", "Москва", "Мухино", "Муром", "Мюнхен", "Мурманск"];
let numbers = cities.map((city) => city.length);
console.log(numbers);
[ 7, 5, 6, 6, 5, 6, 8]

Reduce или самый простой метод в массивах #

Это действительно самый простой метод, потому что он принципиально он объединяет работу двух уже известных нам метода map и filter.

map создаёт новый массив, меняя каждый элемент массива индивидуально. filter создаёт новый массив убирая элементы, которые не соответствуют условиям. reduce в свою очередь, берёт все элементы в массиве, складывает их в новое значение.

Я подготовил пару задач на сегодня и ещё пару для следующей статьи, где мы потрогаем его ещё раз. reduce помогает провести операцию с каждым элементом массива и сохранить одно результирующее значение всей работы.

Например, мы можем найти сумму или среднее арифметическое всех чисел массива. Давайте начнём с суммы:

let array = [11, 31, 4, 5, 7, 6, 1, 3, 44, 115];
let sum = array.reduce((result, current) => result + current);
console.log(sum);

Я пересчитал на калькуляторе. Всё верно. Колбэк функция передаваемая методу reduce имеет результат и актуальный элемент массива. Начальное значение результата в таком случае будет равно первому элементу массива. Среднее арифметическое можно найти просто поделив сумму на длину массива.

let array = [11, 31, 4, 5, 7, 6, 1, 3, 44, 115];
let sum = array.reduce((result, current) => result + current);
let arithmeticAverage = sum/array.length;
console.log(arithmeticAverage.toFixed(2)); 
// 22.70

Метод reduce принимает функцию и если хотите начальное значение результата. Сама колбэк функция может принимать помимо результата и актуального элемента его индекс и сам массив.

let output = array.reduce(function(result, currentItem, cirrentIndex, inputArray), resultStartValue => functionLogic);

Ещё несколько примеров рассмотрено по ссылкам в конце урока.

Some and every - методы проверки #

Они возвращают булевое значение если хоть один - some или каждый(every) соответствует условию.

let cities = ["Могилёв", "Минск", "Москва", "Мухино", "Муром", "Мюнхен", "Мурманск"];
let checkSome = cities.some(city => city==="Могилёв");
console.log(checkSome);

let checkEvery = cities.every((city) => city[0] === "М");
console.log(checkEvery);

Домашнее задание #

Прочитать весь материал в дополнительных ссылках

Дополнительные ссылки #

  1. developer.mozilla.org - map
  2. developer.mozilla.org - every
  3. developer.mozilla.org - filter
  4. developer.mozilla.org - reduce
  5. developer.mozilla.org - some
  6. developer.mozilla.org - sort
  7. Как использовать Map, Filter и Reduce в JavaScript
  8. Полезные приёмы работы с массивами в JavaScript
comments powered by Disqus