Map(), filter() и reduce() в JavaScript

Map(), filter() и reduce() в JavaScript

Перевод публикуется с сокращениями, автор оригинальной статьи A ditya D hanraj T iwari.

Методы массивов map, filter и reduce – по сути, лишь некоторые из наиболее известных и простых в использовании функций высшего порядка, которые обеспечивают обратный вызов для каждого элемента. В этой статье мы рассмотрим, как применение map(), filter() и reduce() поможет сделать код:

  • понятным;
  • менее подверженным побочным эффектам, т. к. эти методы не изменяют массив, а создают новый;
  • избегающим явных циклов.

Приступим к рассмотрению.

Представим ситуацию, в которой есть несколько записей для студентов с атрибутами: name, ID и marks.

Постановка задачи: получить имена студентов и записать их заглавными буквами.

Ожидаемый результат:

Существует несколько способов достижения цели:

Во всех вышеупомянутых примерах создается пустой массив для хранения результата. Как в for(. of) , так и в for() нужно явно перебирать массивы, что делает код более запутанным.

Решение с помощью map()

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

Метод map() принимает два аргумента: функцию обратного вызова и необязательное значение объекта.

Обратный вызов map() выполняется для каждого элемента исходного массива и возвращает новое значение в результирующий.

Если thisValue не задано, функция обратного вызова будет привязана к объекту, который ее вызвал (это значение зависит от выражения вызывающего объекта). В нашем примере thisValue будет привязываться к studentRecords.

filter() возвращает только те элементы из массива, которые удовлетворяют заданным критериям.

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

Ожидаемый результат:

Решение: используем filter() для выбора записей, удовлетворяющих заданному условию (т. е. больше 50 баллов).

Постановка задачи: получить информацию о студентах, набравших более 50 баллов и имеющих id больше 120.

Решение: как показано в приведенном выше фрагменте кода, используя filter() с несколькими условиями для фильтрации данных, мы можем эффективно справиться с задачей.

Работа filter():

filter() принимает функцию обратного вызова, которая возвращает значение bool. Если она возвращает true, то объект добавляется в результирующий массив. В противном случае объект игнорируется.

Точно так же, как map() и filter(), reduce() выполняет обратный вызов для каждого элемента массива. Чтобы лучше понять reduce, сначала нужно рассмотреть два термина: «accumulator» и «reducer».

A ccumulator – это значение, которое мы получаем в конечном итоге, а reducer – действие, которое следует выполнить для его получения. Важно помнить, что reducer всегда будет возвращать только одно значение.

Постановка задачи: на этот раз необходимо знать общую сумму баллов студентов.

Работа reduce():

Давайте разберемся в работе reduce r шаг за шагом:

  1. reduce() принимает accumulator, текущее значение, выражение и initialValue в качестве параметра, используемого для инициализации accumulator (обратите внимание, что в нашем примере initialValue = 0);
  2. reduce() принимает первый элемент массива в качестве текущего значения и accumulator, а затем выполняет требуемую операцию (как при сложении двух значений в нашем примере) и сохраняет результат в accumulator;
  3. Затем accumulator заменяется ранее рассчитанным accumulator, и текущее значение устанавливается на второй элемент массива. Необходимая операция выполняется и accumulator обновляется с новым результатом.
  4. Шаг 3 выполняется, пока все элементы массива не будут перебраны.
  5. Метод возвращает значение accumulator.

Чтобы сравнить наши знания с фактической работой reduce(), рассмотрим значения «accumulator» и «curr_value» для каждой итерации из приведенного выше примера.

Из журнала видно, что accumulator начинается со значения 0 и на каждом шаге его значение обновляется суммой «previous value» и «curr_value».

Теперь объединим возможности map(), filter() и reduce()

Пример 1. map() и filter()

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

Решение: сначала мы отфильтровали данные с помощью filter(), а затем использовали map(), чтобы получить только атрибут name.

Примечание: Вы можете связать map() и filter(), так как они возвращают массивы.

Пример 2. filter() и reduce()

Постановка задачи: напечатаем сумму баллов студентов с id больше 120.

Решение: сначала выбрали студентов с идентификатором больше 120 с помощью filter(), а потом передали отфильтрованный массив студентов в reduce(), чтобы получить сумму их баллов.

Примечание: вы можете связать reduce() после map() и filter(), поскольку они возвращают массивы, но не можете связать map() и filter() после reduce(), т. к. он возвращает единственное значение.

Пример 3. map(), filter() и reduce()

Постановка задачи: вывести общее количество студентов с баллами больше 50, полученными после начисления поощрения в 15 баллов.

  1. Используя map(), добавляется поощрение в 15 баллов студентам, набравшим менее 50 баллов.
  2. Затем, используем filter() для массива студентов, возвращаемого функцией map(). Так мы найдем всех студентов с отметками больше 50.
  3. Наконец, мы использовали функцию reduce() для возвращаемого функцией filter() массива студентов, чтобы вернуть сумму оценок.

В этом гайде мы разобрались, как map(), filter() и reduce() могут облегчить жизнь разработчику, сократив количество ненужных явных циклов и объявлений пустых массивов. Это сделает код более функциональным и легким для понимания. Попробуйте заменять циклы этими методами всякий раз, когда у вас появится такая возможность. Удачи!