Что делают map, filter и reduce?
Функции map, filter и reduce — это встроенные функции высшего порядка, применяемые к коллекциям (массивам, спискам, последовательностям и т. д.) во многих языках программирования: JavaScript, Python, Swift, Java (через стримы), Ruby, Go (частично через собственную реализацию) и других. Они являются основой функционального подхода к обработке данных, позволяя писать декларативный, лаконичный и читаемый код.
1. map — отображение (трансформация) коллекции
Что делает:
Функция map применяет переданную функцию ко всем элементам коллекции, возвращая новую коллекцию с теми же размерами, но с изменёнными значениями.
Сигнатура (на примере JavaScript):
array.map(callback(currentValue, index, array)) → newArray
Сигнатура (на примере Swift):
array.map { element in
// return transformedElement
}
Пример:
JavaScript:
const numbers = \[1, 2, 3\];
const doubled = numbers.map(x => x \* 2); // \[2, 4, 6\]
Swift:
let numbers = \[1, 2, 3\]
let doubled = numbers.map { $0 \* 2 } // \[2, 4, 6\]
Python:
numbers = \[1, 2, 3\]
doubled = list(map(lambda x: x \* 2, numbers)) # \[2, 4, 6\]
Ключевые особенности:
-
Не изменяет исходную коллекцию;
-
Возвращает новый массив/список;
-
Используется для трансформации данных.
2. filter — фильтрация по условию
Что делает:
Функция filter отбирает элементы, удовлетворяющие переданному условию (булевому выражению). Возвращается новая коллекция с подмножеством элементов.
Сигнатура (JavaScript):
array.filter(callback(currentValue, index, array)) → newArray
Пример:
JavaScript:
const numbers = \[1, 2, 3, 4, 5\];
const even = numbers.filter(x => x % 2 === 0); // \[2, 4\]
Python:
numbers = \[1, 2, 3, 4, 5\]
even = list(filter(lambda x: x % 2 == 0, numbers)) # \[2, 4\]
Swift:
let numbers = \[1, 2, 3, 4, 5\]
let even = numbers.filter { $0 % 2 == 0 } // \[2, 4\]
Ключевые особенности:
-
Возвращает коллекцию с теми же типами элементов, но может быть короче;
-
Часто используется для отсеивания «мусора» или выборки нужных значений;
-
Исходная коллекция не модифицируется.
3. reduce — свёртка коллекции в одно значение
Что делает:
Функция reduce агрегирует элементы коллекции в одно итоговое значение, проходя по всем элементам и накапливая результат с помощью заданной логики.
Сигнатура (JavaScript):
array.reduce(callback(accumulator, currentValue, index, array), initialValue)
Сигнатура (Swift):
array.reduce(initialResult) { accumulator, element in
// return newAccumulator
}
Пример:
#### **JavaScript — сумма всех элементов:**
const numbers = \[1, 2, 3, 4\];
const sum = numbers.reduce((acc, curr) => acc + curr, 0); // 10
Python:
from functools import reduce
numbers = \[1, 2, 3, 4\]
sum = reduce(lambda acc, x: acc + x, numbers, 0) # 10
Swift:
let numbers = \[1, 2, 3, 4\]
let sum = numbers.reduce(0) { $0 + $1 } // 10
Другие применения reduce:
-
Сложение/умножение;
-
Объединение строк;
-
Построение объекта из массива;
-
Построение словарей, хэш-таблиц и пр.
Пример — превращение массива в объект (JavaScript):
const arr = \["a", "b", "c"\];
const obj = arr.reduce((acc, key, idx) => {
acc\[key\] = idx;
return acc;
}, {});
// { a: 0, b: 1, c: 2 }
4. Отличия между map, filter и reduce
Функция | Описание | Результат | Входная функция возвращает | Тип результата |
---|---|---|---|---|
map | Преобразует каждый элемент | Коллекция такого же размера | Новый элемент | Массив |
--- | --- | --- | --- | --- |
filter | Отбирает элементы по условию | Коллекция меньшего или равного размера | true или false | Массив |
--- | --- | --- | --- | --- |
reduce | Сводит к одному значению | Одно значение (любой тип) | Новый аккумулятор | Любой |
--- | --- | --- | --- | --- |
5. Вложенные примеры
Комбинирование функций:
const data = \[1, 2, 3, 4, 5, 6\];
// Сначала отфильтруем чётные, затем умножим их на 10
const result = data
.filter(x => x % 2 === 0) // \[2, 4, 6\]
.map(x => x \* 10) // \[20, 40, 60\]
.reduce((a, b) => a + b, 0); // 120
6. Применение на практике
-
map: преобразование данных из одного формата в другой (например, чисел в строки, объектов в DOM-элементы).
-
filter: фильтрация входных данных, удаление невалидных записей, отбор нужных элементов.
-
reduce: подсчёт суммы, объединение строк, агрегация статистики, построение новых структур данных.
7. Поведение и свойства
Не мутируют исходный массив:
Все три функции возвращают новые значения, не изменяя оригинальную коллекцию.
Функции высшего порядка:
Каждая принимает другую функцию в качестве аргумента, что делает их выразительными и гибкими.
Порядок выполнения:
Функции работают последовательно слева направо, особенно важно для reduce, где порядок влияет на результат.
8. Влияние на читаемость и масштабируемость
Использование этих функций позволяет:
-
писать чистый и читаемый код;
-
избегать явных циклов (for, while);
-
выразить намерение (что делается) вместо механики (как делается);
-
легко комбинировать логические шаги обработки данных;
-
избежать мутаций и побочных эффектов (в функциональном стиле).
9. Особенности в разных языках
Язык | Поддержка map / filter / reduce | Особенности |
---|---|---|
JavaScript | Да (Array.prototype.*) | Работает на массивах |
--- | --- | --- |
Python | Да (map(), filter(), reduce()) | reduce требует functools |
--- | --- | --- |
Swift | Да (map, filter, reduce) | Работают на всех коллекциях |
--- | --- | --- |
Ruby | Да (.map, .select, .inject) | Элементы перечисления |
--- | --- | --- |
Java | Да (stream().map()) | Через Stream API |
--- | --- | --- |
C# | Да (.Select(), .Where(), .Aggregate()) | LINQ |
--- | --- | --- |
Go | Нет встроенно, реализуется вручную | Используется for + append |
--- | --- | --- |
Haskell | Да (map, filter, foldr) | По умолчанию, в языке |
--- | --- | --- |
10. Когда не стоит использовать
-
Когда важна производительность на горячих участках: вложенные .map().filter().reduce() могут быть медленнее for.
-
Когда нужна более сложная логика, которую удобнее реализовать в for или forEach.
-
Когда нужен контроль над порядком, индексами, состоянием счётчиков и т. д. — обычный цикл может быть понятнее.