Reduce: примеры (JAVASCRIPT)
reduce(callback: function, initialValue?: any): anyФункция reduce в JavaScript
Метод reduce() выполняет свертку элементов массива, применяя к каждому из них редукционную (аккумулирующую) функцию. Результатом становится одно выходное значение. Метод используется для агрегации данных, преобразования массивов в другие структуры и последовательной обработки.
Синтаксис метода: array.reduce(callback(accumulator, currentValue, index, array), initialValue).
- callback — функция, выполняемая для каждого элемента. Принимает аргументы:
- accumulator — аккумулятор, накапливающий результат.
- currentValue — текущий обрабатываемый элемент.
- index (необязательный) — индекс текущего элемента.
- array (необязательный) — исходный массив.
- initialValue (необязательный) — начальное значение аккумулятора. Если не указано, используется первый элемент массива, а обработка начнется со второго.
Функция возвращает итоговое значение аккумулятора.
Базовые примеры использования
Суммирование чисел в массиве:
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((acc, val) => acc + val, 0);
console.log(sum);10
Без указания начального значения:
const numbers = [5, 10, 15];
const product = numbers.reduce((acc, val) => acc * val);
console.log(product);750
Преобразование массива в объект:
const fruits = ['apple', 'banana', 'apple', 'orange'];
const count = fruits.reduce((acc, fruit) => {
acc[fruit] = (acc[fruit] || 0) + 1;
return acc;
}, {});
console.log(count);{ apple: 2, banana: 1, orange: 1 }Похожие функции в JavaScript
- reduceRight() — выполняет свертку, начиная с конца массива. Подходит для операций, где порядок справа налево важен (например, преобразование чисел).
- map() — создает новый массив, преобразуя каждый элемент. Используется вместо reduce, когда требуется простое преобразование без агрегации.
- filter() — фильтрует элементы по условию. Применяется для выборки данных, тогда как reduce может выполнять фильтрацию с одновременным преобразованием.
- forEach() — выполняет функцию для каждого элемента без создания нового значения. Подходит для простых итераций, но reduce предпочтительнее для накопления результата.
- Array.from() или оператор расширения (...) — альтернативы для преобразования массивоподобных объектов, тогда как reduce может выполнить это с дополнительной логикой.
Типичные ошибки
Попытка использовать reduce для пустого массива без initialValue вызывает исключение.
[].reduce((acc, val) => acc + val);TypeError: Reduce of empty array with no initial value
Изменение исходного массива внутри callback может привести к непредсказуемым результатам.
const arr = [1, 2, 3];
const result = arr.reduce((acc, val, index, array) => {
array.push(val * 2); // Мутация исходного массива
return acc + val;
}, 0);
console.log(result, arr);6 [1, 2, 3, 2, 4, 6]
Использование reduce там, где достаточно более простых методов, например, для поиска максимального значения.
const nums = [5, 2, 9];
// Избыточно:
const max = nums.reduce((a, b) => Math.max(a, b));
// Проще:
const maxSimple = Math.max(...nums);Изменения в последних версиях
Метод reduce был стандартизирован в ECMAScript 5.1 (ES5). С тех пор спецификация остается стабильной. В ECMAScript 2015 (ES6) появились стрелочные функции, которые упрощают синтаксис callback. Современные движки JavaScript оптимизируют производительность reduce для больших массивов.
Расширенные примеры
Плоское преобразование массива объектов:
const data = [
{ category: 'fruit', items: ['apple', 'banana'] },
{ category: 'vegetable', items: ['carrot'] }
];
const allItems = data.reduce((acc, group) => [...acc, ...group.items], []);
console.log(allItems);['apple', 'banana', 'carrot']
Создание цепочки промисов последовательно:
const tasks = [
() => Promise.resolve(1),
(prev) => Promise.resolve(prev + 2),
(prev) => Promise.resolve(prev * 3)
];
tasks.reduce((chain, task) => chain.then(task), Promise.resolve())
.then(result => console.log(result));9
Группировка объектов по свойству с вложенными структурами:
const people = [
{ name: 'Alice', age: 25, city: 'NYC' },
{ name: 'Bob', age: 30, city: 'LA' },
{ name: 'Charlie', age: 25, city: 'NYC' }
];
const grouped = people.reduce((acc, person) => {
const key = person.age;
if (!acc[key]) acc[key] = { count: 0, names: [] };
acc[key].count++;
acc[key].names.push(person.name);
return acc;
}, {});
console.log(grouped);{ '25': { count: 2, names: ['Alice', 'Charlie'] },
'30': { count: 1, names: ['Bob'] } }Вычисление факториала с запоминанием промежуточных значений:
const factorial = (n) =>
[...Array(n).keys()]
.reduce((acc, val, idx) => acc * (idx + 1), 1);
console.log(factorial(5));120
Аналоги в других языках
PHP: функция array_reduce() работает похожим образом, но синтаксис отличается.
$numbers = [1, 2, 3, 4];
$sum = array_reduce($numbers, function($acc, $val) {
return $acc + $val;
}, 0);
echo $sum;10
Python: функция functools.reduce() (требует импорта) или встроенные методы sum, max.
from functools import reduce
numbers = [1, 2, 3, 4]
result = reduce(lambda acc, val: acc + val, numbers, 0)
print(result)10
MySQL: агрегатные функции, например, SUM(), GROUP_CONCAT(), которые применяются в запросах с GROUP BY.
SELECT SUM(column) FROM table;C#: метод Aggregate() из LINQ, с похожей сигнатурой.
int[] numbers = { 1, 2, 3, 4 };
int sum = numbers.Aggregate(0, (acc, val) => acc + val);