Освоите методы фильтрации, сопоставления, сокращения и других методов массива

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

Во всех примерах мы будем обрабатывать один и тот же список телешоу. Вот:

фильтр

Рассмотрим следующий пример, в котором из списка телешоу выбираются только ситкомы. Он все еще использует цикл for:

Мы начинаем с пустого массива ситкомов, перебираем список шоу и вставляем в него только ситкомы.

Можем ли мы сделать лучше, чем это?

Метод массива filter выбирает элементы из списка с помощью функции предиката. filter не изменяет входной массив. Создает новый.

Предикат - это функция, которая проверяет выполнение условия и возвращает логическое значение (true или false).

Вот наша функция предиката, проверяющая, является ли телешоу ситкомом:

function isSitcom(show){
  return show.type === 'sitcom';
}

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

const sitcoms = shows.filter(isSitcom);

Вот и все. Что вы думаете?

карта

Теперь мы хотим преобразовать список объектов телешоу в список строк. Для каждого объекта мы хотим создать новую строку, подобную этой: `${show.name} is a ${show.type}`.

Вот как выполняется преобразование с помощью цикла for:

Мы начинаем с пустого массива строк, просматриваем список телешоу и добавляем в него вычисленные тексты строк.

Я думаю, мы можем добиться большего.

Преобразование массивов в новые массивы с тем же количеством элементов правильно выполняется с map.

Метод массива map преобразует список значений в новый список значений. Новые значения могут быть любыми, от примитивов до объектов. map не изменяет входной массив. Создает новый.

Вот наша функция отображения, преобразующая объект в строку:

function toShowText(show){
  return `${show.name} is a ${show.type}`;
}

Мы можем передать функцию сопоставления методу массива map и выполнить то же преобразование, что и раньше:

const showsTexts = shows.map(toShowText);

Как вы думаете, это выглядит лучше?

уменьшать

Рассмотрим следующий код, использующий цикл for для определения количества шоу для каждого типа:

Мы начинаем с пустого объекта ({}), перебираем список шоу и на каждом шаге увеличиваем счетчик для типа текущего телешоу.

Ниже вы можете проверить, как увеличиваются счетчики на каждом шаге:

Первое шоу - ситком, поэтому счетчик для него установлен на 1. Второй сериал по-прежнему является ситкомом, поэтому количество ситкомов увеличено до 2. Третье шоу - ситком, поэтому счет становится 3. Четвертое шоу - приключение, поэтому счет для ситкомов остается 3, а для приключений устанавливается 1.

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

Метод массива reduce преобразует список значений в новое агрегированное значение с помощью функции редуктора.

На каждом шаге функция редуктора принимает агрегированное значение и текущий элемент и возвращает вновь вычисленное агрегированное значение.

Вот наша функция-редуктор, которая принимает совокупный объект со счетчиками для каждого типа и текущего шоу и возвращает совокупный объект с увеличенными счетчиками для текущего типа шоу:

function countByType(counts, show){
  counts[show.type] = (counts[show.type] || 0 ) + 1;
  return counts;
}

Выражение (counts[show.type] || 0 ) возвращает счетчик для определенного типа шоу, если этот тип существует. В противном случае он оценивается как 0.

Затем мы можем передать функцию редуктора методу reduce и вычислить тот же результат, что и предыдущая логика цикла:

const counts = shows.reduce(countByType, {})

Второй аргумент метода reduce - это начальное значение для вычисленного совокупного значения. В нашем примере это пустой объект ({}).

каждые / некоторые

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

Мы начинаем с переменной areAllSicoms, равной true, и просматриваем список в цикле. Когда мы находим шоу, которое не является ситкомом, мы устанавливаем его на false и останавливаем цикл:

Аналогичным образом мы начинаем с переменной hasSitcoms, равной false, и просматриваем список. Когда мы находим ситком, мы устанавливаем true и останавливаем цикл:

Думаю, мы можем улучшить этот код.

Метод every проверяет, все ли элементы в массиве проходят проверку от функции предиката, и возвращает логическое значение. Если функция предиката возвращает ложное значение, она останавливается и возвращает false. В противном случае он возвращает true после обработки всех элементов.

Метод some проверяет, проходит ли хотя бы один элемент в массиве тест из функции предиката, и возвращает логическое значение. Если функция предиката возвращает истинное значение, она останавливается и возвращает true. В противном случае он возвращает false после обработки всех элементов.

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

function isSitcom(show){
  return show.type === 'sitcom';
}

Теперь мы можем передать функцию предиката в методы массива every и some, чтобы определить, все ли шоу являются ситкомами и есть ли хотя бы один ситком в списке:

Как ты думаешь, сейчас это выглядит лучше?

найти

Ниже приведен пример цикла поиска определенного телешоу в списке:

Мы начинаем с переменной sitcom, равной null, и просматриваем список в цикле. Когда мы находим шоу с определенным именем, мы устанавливаем переменную для ссылки на этот объект и останавливаем цикл.

Можем ли мы упростить этот код?

Метод find возвращает первый элемент из массива, удовлетворяющий функции предиката. Если элемент не найден, возвращается undefined.

Вот наша функция-предикат, проверяющая название шоу, которое мы ищем:

function isFriendsSitcom(show){
  return show.name === 'Friends';
}

Теперь мы можем передать функцию предиката методу массива find:

let sitcom = shows.find(isFriendsSitcom);

Аналогичную функцию предиката можно реализовать с помощью стрелочной функции. Вот как это выглядит:

const sitcom = shows.find(show => show.name === 'Friends');

Как ты думаешь, сейчас это выглядит лучше?

Заключение

Это были одни из самых полезных методов массива, которые вы можете использовать для рефакторинга for циклов. В моей предыдущей статье вы можете найти еще несколько идей о том, как преобразовать код в функциональный стиль.

Спасибо за прочтение.