array_map / array_filter / array_reduce

Yo Yogesh.M Updated 29 Oct 2026
8 min read

array_map(), array_filter(), and array_reduce() are the three core functions for processing arrays without writing loops by hand. Each one expresses a common pattern:

FunctionPatternInput → Output
array_map()Transform every elementN elements → N elements
array_filter()Select elements that pass a testN elements → 0…N elements
array_reduce()Combine all elements into one valueN elements → 1 value

Each takes a callback — a function you provide (often an arrow function) that describes what to do with each element. The loop itself is handled by PHP.

$withGst  = array_map(fn($price) => $price * 1.18, $prices);   // transform
$cheap    = array_filter($prices, fn($price) => $price < 500); // select
$total    = array_reduce($prices, fn($sum, $price) => $sum + $price, 0); // combine

Why Use Them

  • Intent is explicit: "map", "filter", and "reduce" describe what happens, while a foreach loop must be read line by line to understand its purpose.
  • No temporary variables or accidental mutations: each function returns a new value and leaves the input array unchanged.
  • Composable: the result of one can be passed directly to the next, forming a data pipeline.

array_map() — Transform Every Element

Syntax

array_map(?callable $callback, array $array, array ...$arrays): array

Example

<?php
$prices = [100, 250, 499];
$withGst = array_map(fn(float $price): float => round($price * 1.18, 2), $prices);
$labels = array_map(fn(float $price): string => '₹' . number_format($price, 2), $withGst);
echo implode(', ', $labels) . "\n";
echo implode(', ', $prices) . "\n";

Output

₹118.00, ₹295.00, ₹588.82
100, 250, 499

The callback receives each value and returns the new value. The result has the same number of elements, and the original $prices is unchanged.

Keys Are Preserved With One Array

<?php
$prices = ['Pen' => 20, 'Lamp' => 1299];
print_r(array_map(fn(int $price): int => $price * 2, $prices));

Output

Array
(
    [Pen] => 40
    [Lamp] => 2598
)

With a single input array, array_map() keeps the keys. With several arrays, the result is re-indexed.

Accessing Keys in the Callback

The callback receives only values. To use the keys too, pass array_keys() as a second array:

<?php
$prices = ['Pen' => 20, 'Lamp' => 1299];
$lines = array_map(
    fn(string $item, int $price): string => "$item: ₹$price",
    array_keys($prices),
    $prices
);
print_r($lines);

Output

Array
(
    [0] => Pen: ₹20
    [1] => Lamp: ₹1299
)

Combining Several Arrays

When given multiple arrays, the callback receives one element from each, position by position:

<?php
$names = ['Asha', 'Bala', 'Charu'];
$scores = [88, 72, 95];
print_r(array_map(fn(string $name, int $score): string => "$name scored $score", $names, $scores));
echo json_encode(array_map(null, [1, 2], ['a', 'b'])) . "\n";

Output

Array
(
    [0] => Asha scored 88
    [1] => Bala scored 72
    [2] => Charu scored 95
)
[[1,"a"],[2,"b"]]

Passing null as the callback "zips" the arrays into pairs. If the arrays differ in length, shorter ones are padded with null.


array_filter() — Keep Matching Elements

Syntax

array_filter(array $array, ?callable $callback = null, int $mode = 0): array

Example

<?php
$scores = ['Asha' => 88, 'Bala' => 34, 'Charu' => 95, 'Dev' => 39];
$passed = array_filter($scores, fn(int $score): bool => $score >= 40);
print_r($passed);

Output

Array
(
    [Asha] => 88
    [Charu] => 95
)

The callback returns true to keep an element. Keys are preserved — wrap the result in array_values() if you need a list with continuous indexes (for example, before json_encode()).

Filtering by Key or by Key and Value

<?php
$env = ['DB_HOST' => 'localhost', 'DB_PORT' => '3306', 'MAIL_DRIVER' => 'smtp', 'DB_NAME' => 'shop'];
$dbSettings = array_filter(
    $env,
    fn(string $key): bool => str_starts_with($key, 'DB_'),
    ARRAY_FILTER_USE_KEY
);
$stock = ['Pen' => 100, 'Lamp' => 0, 'Bag' => 4, 'Mug' => 12];
$available = array_filter(
    $stock,
    fn(int $qty, string $item): bool => $qty > 0 && $item !== 'Mug',
    ARRAY_FILTER_USE_BOTH
);
echo implode(', ', array_keys($dbSettings)) . "\n";
echo implode(', ', array_keys($available)) . "\n";

Output

DB_HOST, DB_PORT, DB_NAME
Pen, Bag
ModeCallback Receives
0 (default)The value
ARRAY_FILTER_USE_KEYThe key
ARRAY_FILTER_USE_BOTHThe value and the key

Without a Callback

Without a callback, array_filter() removes all falsy values — false, null, 0, 0.0, '', '0', and []. This is convenient for removing empty entries but also removes valid zeros. Pass an explicit callback for user data (see Remove Array Items).


array_reduce() — Combine Into One Value

Syntax

array_reduce(array $array, callable $callback, mixed $initial = null): mixed

The callback receives an accumulator (often called $carry) and the current element. Whatever it returns becomes the accumulator for the next element. After the last element, the accumulator is the result.

Example: Sum

<?php
$cart = [499, 1299, 89];
$total = array_reduce($cart, fn(int $carry, int $price): int => $carry + $price, 0);
echo $total . "\n";

Output

1887

Step by Step

Step$carry (before)$priceReturned
10 (initial)499499
249912991798
31798891887

For a simple sum, array_sum() is shorter. array_reduce() is valuable when the combination is more complex.

Example: Finding the Most Expensive Product

<?php
$products = [
    ['name' => 'Gel Pen', 'price' => 20],
    ['name' => 'Desk Lamp', 'price' => 1299],
    ['name' => 'Backpack', 'price' => 899],
];
$mostExpensive = array_reduce(
    $products,
    fn(?array $carry, array $product): array =>
        $carry === null || $product['price'] > $carry['price'] ? $product : $carry
);
echo $mostExpensive['name'] . "\n";

Output

Desk Lamp

With no initial value, the accumulator starts as null; the first product then becomes the "best so far", and each later product replaces it only if it is more expensive.

Example: Counting by Group

<?php
$statuses = ['paid', 'pending', 'paid', 'cancelled', 'paid'];
$counts = array_reduce($statuses, function (array $carry, string $status): array {
    $carry[$status] = ($carry[$status] ?? 0) + 1;
    return $carry;
}, []);
print_r($counts);

Output

Array
(
    [paid] => 3
    [pending] => 1
    [cancelled] => 1
)

The accumulator can be an array, so array_reduce() can build any structure.

Always Provide an Initial Value When Possible

<?php
var_dump(array_reduce([], fn($carry, $n) => $carry + $n));
var_dump(array_reduce([], fn($carry, $n) => $carry + $n, 0));

Output

NULL
int(0)

For an empty array, the callback never runs and the initial value is returned. Without an explicit initial value, that is null — which can cause type errors later. Pass a sensible starting value (0, '', []).


Combining Them: A Data Pipeline

<?php
$orders = [
    ['id' => 1, 'customer' => 'Asha', 'total' => 1250, 'status' => 'paid'],
    ['id' => 2, 'customer' => 'Bala', 'total' => 640, 'status' => 'pending'],
    ['id' => 3, 'customer' => 'Charu', 'total' => 3200, 'status' => 'paid'],
    ['id' => 4, 'customer' => 'Dev', 'total' => 980, 'status' => 'paid'],
];
$paidOrders = array_filter($orders, fn(array $o): bool => $o['status'] === 'paid');
$totals = array_map(fn(array $o): int => $o['total'], $paidOrders);
$revenue = array_reduce($totals, fn(int $sum, int $total): int => $sum + $total, 0);
$largest = array_reduce(
    $paidOrders,
    fn(?array $best, array $o): array => $best === null || $o['total'] > $best['total'] ? $o : $best
);
echo "Paid orders: " . count($paidOrders) . "\n";
echo "Revenue: ₹" . number_format($revenue) . "\n";
echo "Average order: ₹" . number_format($revenue / count($paidOrders)) . "\n";
echo "Largest: {$largest['customer']} (₹" . number_format($largest['total']) . ")\n";

Output

Paid orders: 3
Revenue: ₹5,430
Average order: ₹1,810
Largest: Charu (₹3,200)

Step-by-Step Explanation

  1. Filter: keep only paid orders (orders 1, 3, and 4).
  2. Map: turn each order into its total.
  3. Reduce: add the totals: 1250 + 3200 + 980 = 5430.
  4. Reduce again: find the order with the highest total. Each step has one responsibility and produces a new array, so intermediate results can be inspected or reused. (array_sum(array_column($paidOrders, 'total')) would compute the revenue more directly; the explicit steps illustrate the pattern.)

With the Pipe Operator (PHP 8.5+)

$revenue = $orders
    |> (fn(array $o) => array_filter($o, fn($x) => $x['status'] === 'paid'))
    |> (fn(array $o) => array_column($o, 'total'))
    |> array_sum(...);

The pipe operator passes each result into the next step, reading top to bottom.


When to Use a foreach Loop Instead

Use the functions when…Use foreach when…
Each step is a short, pure transformationThe body performs several actions or side effects (saving, sending, logging)
You need a new array and want to keep the originalYou must stop early (break) — or use array_find() in PHP 8.4+
The logic fits in a small callbackThe logic needs many variables or complex conditions

Both styles are good PHP. Choose the one that makes the code easiest to read.


Common Mistakes

Wrong Argument Order

array_map($callback, $array) takes the callback first; array_filter($array, $callback) and array_reduce($array, $callback) take the array first. Mixing them up causes a TypeError.

Expecting array_filter() to Re-index

Effect: Gaps in keys and JSON objects instead of arrays. Fix: array_values(array_filter(...)).

Forgetting the Initial Value in array_reduce()

Effect: null result for empty arrays. Fix: Pass an initial value matching the expected result type.

Expecting Keys in the array_map() Callback

Effect: Only values are passed. Fix: Pass array_keys($array) as an additional array, or use foreach.

Side Effects Inside Callbacks

Effect: Hidden actions (database writes, emails) inside a "transformation" make code hard to understand. Fix: Keep callbacks pure; perform side effects in a clear loop.


Best Practices

  • Use array_map() to transform, array_filter() to select, and array_reduce() to combine.
  • Write short callbacks as typed arrow functions.
  • Re-index filtered lists with array_values() when order and continuity matter.
  • Always give array_reduce() an initial value.
  • Prefer specialized functions (array_sum(), array_column(), array_find()) when they express the task directly. Official reference: https://www.php.net/manual/en/function.array-map.php

0 Comments

Reviewed before they appear

No comments yet.

Data Mining
Introduction to Data Mining Data Mining Implementation Process Data Mining Architecture Data Mining Techniques KDD: Knowledge Discovery in Databases History of Data Mining Data Mining Tools Data Mining vs Machine Learning Facebook Data Mining Social Media Data Mining Methods Clustering in Data Mining Text Data Mining Bagging vs Boosting Data Mining vs Data Warehousing Social Media Data Mining Data Mining: Bayesian Classifiers Data Mining: World Wide Web Different Types of Clustering Bitcoin Mining and Blockchain Data Mining Orange Data Mining Data Mining vs Big Data Decision Tree Induction Educational Data Mining Data Mining in Healthcare Apriori Algorithm Data Integration in Data Mining Difference Between Data Mining and Text Mining Discretization in Data Mining Redundancy and Correlation in Data Mining Classification of Data Mining Systems Classification Algorithms in Data Mining Data Generalization in Data Mining Classification and Prediction in Data Mining Regression in Data Mining What Is an Outlier in Data Mining Data Cleaning in Data Mining Data Processing in Data Mining Data Mining Task Primitives Web Content Mining, Web Structure Mining, and Web Usage Mini Binning in Data Mining KDD vs. Data Mining Noise in Data Mining BIRCH in Data Mining Stemming in Data Mining Feature Transformation in Data Mining Visual and Audio Data Mining Class Comparison Methods in Data Mining Data Selection in Data Mining Tasks and Functionalities of Data Mining Ubiquitous and Invisible Data Mining Importance of Data Mining Data Quality in Data Mining Mining Frequent Patterns in Data Mining Data Warehouse and OLAP Technology for Data Mining Need for Data Mining Pattern Evaluation Methods in Data Mining Logarithms and Exponents in Complexity Analysis Time Series Clustering What is the C4.5 Algorithm and How Does It Work? Expanding Contractions in Text Mining Cosine Similarity in Data Mining Lazy Learning in Data Mining Neural Networks in Data Mining Building a Text Normalizer Shallow Parsing Data Pipeline Orchestration Big Data vs Small Data Myths of Data Mining Data Reduction in Data Mining Data Mining Models Difference Between Data Mining and Data Science Difference Between Data Mining and Statistics Difference Between Data Mining and Web Mining Difference Between Data Mining and Data Analysis Difference Between Business Intelligence and Data Mining Difference Between Data Mining and Data Visualization Data Mining vs Data Analytics Types of Data Mining Difference Between Data Profiling and Data Mining Predictive Analytics vs Data Mining Difference Between Data Mining and OLAP Descriptive and Predictive Data Mining Difference Between Spatial and Temporal Data Mining Difference Between Classification and Clustering in Data Min Hierarchical Clustering in Data Mining Density-Based Clustering in Data Mining What Is Aggregation in Data Mining?
Ask about this post
AI Ask about this post

Ask questions about array_map / array_filter / array_reduce and get answers drawn from it.

Signed-in readers only.