Функции массивов в PHP: array_map, array_filter и array_reduce — понятное руководство с примерами
Функции массивов — одна из сильных сторон PHP. Правильное использование array_map, array_filter и array_reduce помогает писать короче, читабельнее и безопаснее. В этом руководстве мы разберём каждую из них, покажем типичные сценарии и ошибки, а также соберём «конвейер» обработки данных.
Когда и зачем использовать array_map, array_filter, array_reduce
- array_map — применяет функцию к каждому элементу и возвращает новый массив с изменёнными значениями.
- array_filter — отбирает элементы по условию (предикату). Ключи сохраняются.
- array_reduce — сворачивает массив к одному значению (сумма, строка, индекс и т. п.).
array_map: преобразуем данные
Пусть у нас список цен, и мы хотим добавить НДС (20%) и округлить:
$prices = [100, 250.5, 300];
$withVat = array_map(fn($p) => round($p * 1.2, 2), $prices);
print_r($withVat);
// [120, 300.6, 360]
array_map сохраняет ключи первого массива. Если вы передаёте несколько массивов, значения берутся по индексам (не по ключам), а ключи наследуются от первого массива:
$a = [10, 20, 30];
$b = [1, 2, 3];
$sum = array_map(fn($x, $y) => $x + $y, $a, $b);
// [11, 22, 33]
Практический пример с товарами:
$products = [
['id' => 1, 'name' => 'Mouse', 'price' => 990, 'active' => true],
['id' => 2, 'name' => 'Keyboard', 'price' => 1990, 'active' => false],
['id' => 3, 'name' => 'Monitor', 'price' => 10990, 'active' => true],
];
$withVat = array_map(function ($p) {
$p['price_vat'] = round($p['price'] * 1.2);
return $p;
}, $products);
Советы по array_map
- Используйте короткие стрелочные функции
fn(...)для лаконичности. - Если нужно изменить массив «на месте», рассмотрите
array_walkс передачей по ссылке, но чаще проще создать новый массив черезarray_map.
array_filter: отбираем нужные элементы
По умолчанию сохраняет исходные ключи. Это удобно, но иногда требуется переиндексация через array_values.
$users = [
['id' => 1, 'name' => 'Anna', 'age' => 17, 'active' => true],
['id' => 2, 'name' => 'Ivan', 'age' => 25, 'active' => true],
['id' => 3, 'name' => 'Petr', 'age' => 16, 'active' => false],
['id' => 4, 'name' => 'Olga', 'age' => 31, 'active' => true],
];
$adultsActive = array_filter($users, fn($u) => $u['active'] && $u['age'] >= 18);
// Ключи сохранены (1, 3, ...). Если нужен «ровный» список:
$adultsActive = array_values($adultsActive);
Можно учитывать ключи через флаги:
$byId = [
10 => ['id' => 10, 'name' => 'Alex'],
15 => ['id' => 15, 'name' => 'Bob'],
20 => ['id' => 20, 'name' => 'Kate'],
];
$filtered = array_filter(
$byId,
fn($user, $id) => $id >= 15,
ARRAY_FILTER_USE_BOTH
);
// Останутся элементы с ключами 15 и 20
Советы по array_filter
- Для фильтрации по ключам используйте
ARRAY_FILTER_USE_KEYилиARRAY_FILTER_USE_BOTH. - Не забывайте о
array_values, если нужен плотный индексированный массив после фильтрации.
array_reduce: сворачиваем к одному значению
Часто применяют для сумм, подсчётов и построения индексов.
$nums = [10, 20, 30];
$sum = array_reduce($nums, fn($carry, $n) => $carry + $n, 0);
// 60
Построим индекс по id (удобно для быстрого поиска):
$byId = array_reduce($users, function ($acc, $u) {
$acc[$u['id']] = $u;
return $acc;
}, []);
// Теперь $byId[2] вернёт пользователя с id=2 за O(1)
Средняя цена активных товаров:
$active = array_filter($products, fn($p) => $p['active']);
$prices = array_column($active, 'price');
$sum = array_reduce($prices, fn($c, $p) => $c + $p, 0);
$avg = count($prices) ? $sum / count($prices) : 0;
Комбинируем: «конвейер» обработки
Допустим, нужно: взять активных пользователей 18+, у каждого сформировать «ярлык» и получить массив этих ярлыков.
$result = array_map(
fn($u) => sprintf('%s (%d)', $u['name'], $u['age']),
array_values(array_filter($users, fn($u) => $u['active'] && $u['age'] >= 18))
);
print_r($result);
// ["Ivan (25)", "Olga (31)"]
Типичные ошибки и подводные камни
- Забытая переиндексация после array_filter. Если порядок важен или нужен «чистый» индекс, вызывайте
array_values. - Ожидание сопоставления по ключам в array_map. При нескольких массивах сопоставление идёт по позиции, ключи берутся от первого массива.
- Чрезмерное увлечение функциями высшего порядка. Для очень больших массивов иногда быстрее и понятнее обычный
foreach(меньше накладных расходов на вызовы функций). - Изменение исходных данных.
array_mapне меняет исходный массив — он возвращает новый. Если нужно модифицировать «на месте», используйтеarray_walkи ссылки или явный цикл.
Практический мини-кейс: подготовка данных для отчёта
Задача: взять список заказов, оставить только оплаченные, округлить сумму с учётом комиссий и посчитать общую выручку.
$orders = [
['id' => 101, 'amount' => 1200.4, 'paid' => true],
['id' => 102, 'amount' => 800.1, 'paid' => false],
['id' => 103, 'amount' => 350.0, 'paid' => true],
];
$paid = array_values(array_filter($orders, fn($o) => $o['paid']));
$normalized = array_map(function ($o) {
$o['final'] = round($o['amount'] * 1.015, 2); // комиссия 1.5%
return $o;
}, $paid);
$total = array_reduce($normalized, fn($sum, $o) => $sum + $o['final'], 0.0);
print_r($normalized);
print_r($total);
Производительность и читабельность
- Для небольших и средних массивов
array_map/filter/reduceдают чистый и декларативный код. - Для миллионов элементов рассмотрите
foreach, генераторы, потоковую обработку и избегайте лишних промежуточных массивов. - Старайтесь называть колбэки понятно, особенно если логика не помещается в одну строку.
Краткий «шпаргалка»
array_map(fn($x) => ... , $arr)— преобразовать элементы.array_filter($arr, fn($x) => условие)— отфильтровать; ключи сохраняются.array_reduce($arr, fn($carry, $x) => ..., $initial)— свести к одному значению.ARRAY_FILTER_USE_KEY,ARRAY_FILTER_USE_BOTH— фильтрация по ключам и значениям одновременно.array_values()— переиндексация после фильтра.
Хотите системно прокачать PHP и уверенно работать с данными, базами и веб-приложениями? Посмотрите практический курс «PHP и MySQL с Нуля до Гуру 3.0» — стартуйте с нуля и дойдите до продвинутых проектов.
-
Создано 07.11.2025 17:01:40
-
Михаил Русаков

Комментарии (0):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.