Функция array_reduce() в PHP: полное руководство
Функция array_reduce() в PHP — мощный инструмент для обработки массивов и сведения их к единственному значению. Применяется для суммирования и других задач.
array_reduce() проходит по массиву поэлементно и сворачивает его до единственного значения — суммы, счётчика, наибольшего элемента, перестроенной структуры и т. д. На каждой итерации функция передаёт в ваш callback два аргумента: накопленный до этого момента результат (аккумулятор, традиционно именуемый $carry) и текущий элемент ($item). То, что возвращает callback, становится новым аккумулятором для следующей итерации, а итоговый аккумулятор и есть возвращаемое значение array_reduce().
Используйте её всякий раз, когда нужно свернуть весь массив в один результат, а одного вызова array_sum(), array_filter() или array_map() недостаточно — например, при суммировании только определённых элементов, построении таблицы поиска или нахождении максимума с нестандартной логикой. Это руководство охватывает синтаксис, поведение аккумулятора, распространённые паттерны и типичные ловушки.
Синтаксис
array_reduce(array $array, callable $callback, mixed $initial = null): mixed| Параметр | Описание |
|---|---|
$array | Входной массив для сворачивания. |
$callback | Функция, вызываемая для каждого элемента. Получает ($carry, $item) и обязана вернуть новый аккумулятор. |
$initial | Необязательное начальное значение для $carry. По умолчанию null. |
Сигнатура callback:
function (mixed $carry, mixed $item): mixed$carryсодержит накопленный на данный момент результат — при первом вызове равен$initial.$item— текущий элемент массива.- Возвращаемое значение становится
$carryдля следующего элемента. Забытыйreturn— самая частая ошибка.
array_reduce() игнорирует ключи массива; в callback передаются только значения. Если ключи нужны, выполните итерацию вручную или предварительно вызовите array_keys().
Типичные сценарии использования
array_reduce() особенно полезна, когда множество значений должно превратиться в одно. Распространённые паттерны:
- Суммирование или перемножение элементов
- Подсчёт элементов, удовлетворяющих условию
- Построение ассоциативного массива (таблицы поиска) из списка
- Выравнивание или объединение вложенных массивов
- Нахождение минимума или максимума с нестандартной логикой сравнения
Пример 1: суммирование элементов массива
Простейший вариант — сложение чисел. Callback прибавляет текущий элемент к текущей сумме, а 0, переданный как $initial, задаёт начальное значение суммы.
$carry хранит текущую сумму, начиная с 0, а $item — текущее число. Для простого суммирования можно использовать встроенную array_sum() — array_reduce() становится полезной, когда логика накопления требует нестандартных действий (суммировать только чётные числа, перемножать и т. д.).
Пример 2: подсчёт элементов массива
Элементы можно считать, увеличивая аккумулятор на единицу при каждой итерации вместо добавления значения элемента. Обратите внимание: $item здесь намеренно не используется — array_reduce() не обязывает вас применять текущий элемент.
В этом примере переменная $carry отслеживает счётчик, начиная с 0. Переменная $item содержит обрабатываемый элемент, но в данном случае не используется.
Пример 3: построение ассоциативного массива (таблицы поиска)
Очень практичный паттерн — превращение списка записей в индексированную таблицу поиска, чтобы находить запись по имени без перебора всего списка. Аккумулятор начинается как пустой array и получает по одному ключу на каждую запись.
<?php
$data = array(
array("name" => "John", "age" => 25),
array("name" => "Jane", "age" => 30),
array("name" => "Jim", "age" => 35)
);
$people = array_reduce($data, function($carry, $item) {
$carry[$item["name"]] = $item["age"];
return $carry;
}, array());
print_r($people);
?>Результат: Array ( [John] => 25 [Jane] => 30 [Jim] => 35 ). Каждый $item — одна запись о человеке; callback использует имя как ключ и возраст как значение, возвращая обновлённый array, чтобы следующая итерация могла добавить в него новый элемент.
Пример 4: выравнивание вложенных массивов
Вложенный массив массивов можно выровнять в один плоский array, объединяя каждый вложенный array с аккумулятором. Поскольку array_merge() возвращает новый array, возврат его результата корректно увеличивает $carry.
Здесь входные данные — [[1, 2], [3, 4], [5]]. Каждый $item — один внутренний array, а array_merge() добавляет его значения к $carry, получая единый плоский список. (Выравнивание происходит только на один уровень в глубину.)
Пример 5: объединение нескольких массивов в один
Та же идея объединения работает для слияния набора отдельных массивов. Оберните массивы, которые нужно соединить, во внешний array и объединяйте каждый с аккумулятором.
$colors и $fruits объединяются по порядку, образуя один общий array. При наличии множества массивов это чище, чем последовательно вызывать array_merge() вручную.
Использование стрелочных функций
Начиная с PHP 7.4 callback можно записать в виде лаконичной стрелочной функции. Она автоматически захватывает внешние переменные и неявно возвращает своё выражение, устраняя легко забываемый return:
<?php
$numbers = [1, 2, 3, 4, 5];
$sum = array_reduce($numbers, fn($carry, $item) => $carry + $item, 0);
echo $sum; // 15
?>Частые ошибки
- Всегда возвращайте значение из callback. Если какая-то ветка кода забывает вернуть
$carry, аккумулятор становитсяnullи всё последующее ломается. Стрелочные функции эту проблему исключают. - Следите за начальным значением. Без
$initialпеременная$carryначинается какnull. Для числовых сумм передавайте0; для построения массива —[]. Иначе первыйarray_merge(null, …)илиnull + 1вызовет ошибку или предупреждение. - Пустой array возвращает начальное значение.
array_reduce([], $fn, 0)вернёт0; без начального значения —null. Обрабатывайте этот случай, если пустые входные данные возможны. - Ключи игнорируются. В callback передаются только значения. Если ключи нужны, применяйте
array_reduce()к результатуarray_keys($arr).
Следующий пример ищет максимальное значение без начального значения, особым образом обрабатывая первый элемент:
<?php
$numbers = [10, 5, 20, 8];
$max = array_reduce($numbers, function ($carry, $item) {
return ($carry === null || $item > $carry) ? $item : $carry;
});
echo $max; // 20
?>Связанные функции
array_map()— преобразует каждый элемент в новый array (один к одному), а не сворачивает к одному значению.array_filter()— оставляет только элементы, прошедшие проверку.array_sum()— удобный способ для простого суммирования.array_merge()— объединяет массивы напрямую, когда логика обработки каждого элемента не нужна.
Заключение
array_reduce() сворачивает array в единственное значение, пропуская аккумулятор через callback. Как только вы усвоите поток ($carry, $item) => newCarry, вы сможете суммировать, считать, строить таблицы поиска, выравнивать и объединять с помощью одного лаконичного инструмента. Помните два правила, предотвращающих большинство ошибок: всегда возвращайте новый аккумулятор и выбирайте значение $initial, соответствующее типу строящегося результата.