Reduce: примеры (JAVASCRIPT)

Работа с функцией 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 для больших массивов.

Расширенные примеры

Плоское преобразование массива объектов:

Пример javascript
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']

Создание цепочки промисов последовательно:

Пример javascript
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

Группировка объектов по свойству с вложенными структурами:

Пример javascript
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'] } }

Вычисление факториала с запоминанием промежуточных значений:

Пример javascript
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);

JS reduce function comments

En
Reduce Executes a reducer function on each element of the array, resulting in a single output value.