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() могут облегчить жизнь разработчику, сократив количество ненужных явных циклов и объявлений пустых массивов. Это сделает код более функциональным и легким для понимания. Попробуйте заменять циклы этими методами всякий раз, когда у вас появится такая возможность. Удачи!

Вы пропустили

AEGIS Algorithms Android Angular Apache Airflow Apache Druid Apache Flink Apache Spark API API Canvas AppSec Architecture Artificial Intelligence Astro Authentication Authorization AutoGPT AWS AWS Aurora AWS Boto3 AWS EC2 AWS Lambda Azure Babylon.js Backend bash Beautiful Soup Bento UI Big Data Binary Tree Browser API Bun Career Cassandra Charts ChatGPT Chrome Extension Clean Code CLI ClickHouse Coding Codux Combine Compose Computer Context Fusion Copilot Cosmo Route CProgramming cron Cryptography CSS CTF Cypress DALL-E Data Analysis Data science Database dbt dbt Cloud deno Design Design Patterns Detekt Development Distributed Systems Django Docker Docker Hub Drizzle DRY DuckDB Express FastAPI Flask Flutter For Beginners Front End Development Game Development GCN GCP Geospatial Git GitHub Actions GitHub Pages Gitlab GMS GoFr Golang Google Google Sheets Google Wire GPT-3 GPT3 Gradio Gradle Grafana Graphic Design GraphQL gRPC Guidance HMS Hotwire HTML Huawei HuggingFace IndexedDB InfoSec Interview iOS Jackknife Java JavaScript Jetpack Compose JSON Kafka Kotlin Kubernetes LangChain Laravel Linux LlaMA LLM localStorage Logging Machine Learning Magento Math Mermaid Micro Frontends Mobile Mobile App Development mondayDB MongoDB Mongoose MySQL Naming NestJS NET NetMock Networks NextJS NLP Node.js Nodejs NoSQL NPM OOP OpenAI OTP Pandas PDF PHP Playwright Plotly Polars PostgreSQL Prefect Productivity Programming Prometheus Puppeteer Pushover Python Pytorch Quarkus Rabbitmq RAG Ramda Raspberry Pi React React Native Reactor Redis REST API Revolut Riverpod RProgramming Ruby Ruby on Rails Rust Scalene SCDB ScyllaDB Selenium Servers Sklearn SLO SnowFlake Snowkase Software Architecture Software Development Solara Solid Spring Boot SQL SQLite Streamlit SudoLang Supabase Swift SwiftUI Tailwind CSS Taipy Terraform Testing Transformers TURN TypeScript Ubuntu UI Design Unix UX UX Design Vim Vite VSCode Vue Web Architecture Web Components Web Development Web Frameworks Web Scraping Web-разработка Webassembly Websocket Whisper Widgets WordPress YAML YouTube Zed Наука о данных Разное Тренды

Современный подход к разработке с использованием Next.js