PHP: Функции
2026-02-26 20:44 Diff

Последняя функция из нашей тройки — array_reduce или свертка. В других языках она называется accumulate или fold. Эта функция используется для агрегации. Она устроена немного сложнее, чем map и filter, но сохраняет общий подход с передачей функции.

Как обычно, начнем с примера на циклах. Реализуем код, находящий самого взрослого пользователя:

Основное отличие агрегации от отображения и фильтрации заключается в том, что результатом агрегации может быть любой тип данных — как примитивный, так и составной. Например, результатом может быть массив. Кроме того, агрегация нередко подразумевает инициализацию начальным значением. В примере выше она выполняется на строчке $oldest = $users[0];.

Посмотрим еще один пример агрегации — группировку имен пользователей по возрасту:

В этом примере результатом агрегации становится массив массивов, который в самом начале инициируется пустым массивом. Значение, которое накапливает результат агрегации, принято называть словом аккумулятор. В примерах выше это $oldest и $usersByAge.

Реализуем первый пример, используя array_reduce:

Функция array_reduce принимает на вход три параметра. Два из них уже традиционны — это коллекция и функция-обработчик, а вот третьим выступает начальное значение аккумулятора. Поиск самого взрослого пользователя аналогичен поиску максимального или минимального числа в массиве. Соответственно, аккумулятор должен быть инициализирован первым пользователем. Этот же аккумулятор возвращается наружу.

Колбэк-функция, передаваемая в array_reduce — это самая важная часть и ключ к пониманию работы всего механизма агрегации. Она принимает на вход два значения:

  • Текущее значение аккумулятора
  • Текущий обрабатываемый элемент

Задача функции — вернуть новое значение аккумулятора. При этом array_reduce никак не анализирует содержимое аккумулятора. Все, что она делает — она передает значение аккумулятора в каждый новый вызов, пока не будет обработана вся коллекция, и в конце концов вернет его наружу. Подчеркнем, что возвращать аккумулятор надо всегда, даже если он не изменился.

Второй пример с использованием array_reduce выглядит так:

Код практически не изменился. Как видите, ушел цикл и появился возврат аккумулятора из анонимной функции.

Перейдем к реализации:

Функция array_reduce очень мощная. Формально, можно работать, используя только ее, потому что она может заменить отображение и фильтрацию. Но делать так не стоит. Агрегация управляет состоянием (аккумулятором) явно. Такой код всегда сложнее и требует больше действий. Поэтому, если задачу возможно решить отображением или фильтрацией, то так и нужно делать.