Функции массивов в PHP: array_map, array_filter и array_reduce — понятное руководство с примерами
Функции массивов — одна из сильных сторон PHP. Правильное использование 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_values.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» — стартуйте с нуля и дойдите до продвинутых проектов.





