Speed Up Array Operations in PHP: array_map, array_filter, array_walk

Learn how to optimize array processing in PHP using array_map, array_filter, and array_walk. Master fast array operations with performance tips and examples.

PHP COURSE
PHP – arrays: declarations, operations, sorting, and functions
Lesson

Arrays are at the heart of PHP programming. We process input data, database/API results, product lists, logs, and even configurations using arrays. To write fast and readable PHP code, it’s worth knowing built-in array functions: arraymap, arrayfilter, and arraywalk. They allow you to:

  • quickly transform elements,
  • efficiently filter data,
  • safely iterate and modify values in place.
Bonus: Code with these functions is usually shorter, more expressive, and — in many cases — faster than manually written loops, since they run optimized C code under the hood.

Basics: what these functions do and when to use them

arraymap — transforming elements

  • Returns a new array, where each element is the result of applying a function to the original element.
  • Does not modify the source array.
  • Can work on one or multiple arrays at once.
  • Keys are preserved if you pass only one array; with multiple arrays, keys are reindexed.
Typical use cases:
  • type conversion (string → int),
  • data normalization (trim, strtolower),
  • combining multiple arrays element by element.

arrayfilter — selecting elements

  • Returns a new array containing only elements where the function returns true.
  • By default, keeps the original keys.
  • If no function is passed, removes all “falsey” values (false, 0, '0', '', null, \[]).
Typical use cases:
  • removing empty values,
  • filtering data by business rules,
  • selecting elements based on value or key.

arraywalk — iteration with side effects (in-place modification)

  • Iterates through an array and calls a function for each element.
  • Can modify values “in place” (by reference).
  • Returns true/false (success/failure), does not return a new array.
  • Good for modifications without allocating a new array, logging, or validation.
Typical use cases:
  • trim/format in place,
  • validation and collecting statistics,
  • lightweight operations with side effects.
Performance note:
  • Built-in functions are fast, but each callback call has overhead. For the simplest tasks, a foreach loop can be just as fast (or faster). Gains are greater when you do more work per element or use built-ins like strtolower directly.
---

PHP Code Examples

arraymap — basics and practice

<?php
declare(strict_types=1);

// 1) Simple transformation: multiply by 2
$numbers = [1, 2, 3, 4];
$doubled = array_map(fn(int $n): int => $n * 2, $numbers);
print_r($doubled); // [1=>2, 2=>4, 3=>6, 4=>8]

// 2) Using built-in function as callback
$words = ['PHP', 'Speed', 'Array'];
$lower = array_map('strtolower', $words); // ['php', 'speed', 'array']

// 3) Normalizing data: trim + strtolower
$raw = ['  Admin ', " USER", "\tGuest\n"];
$normalized = array_map(static function (string $v): string {
    return strtolower(trim($v));
}, $raw);
// ['admin','user','guest']

// 4) Mapping multiple arrays element by element
$firstNames = ['Ada', 'Linus', 'Rasmus'];
$lastNames  = ['Lovelace', 'Torvalds', 'Lerdorf'];
$fullNames = array_map(
    static fn(string $f, string $l): string => "$f $l",
    $firstNames,
    $lastNames
);
print_r($fullNames); // ['Ada Lovelace','Linus Torvalds','Rasmus Lerdorf']

// 5) Using null as callback groups arrays element-wise
$a = [1, 2];
$b = ['x', 'y'];
$zipped = array_map(null, $a, $b); // [[1,'x'],[2,'y']]
print_r($zipped);

Tip: Passing a built-in function name as string (e.g., 'strtolower') is often faster than using a closure, since PHP can call it directly.


arrayfilter — filtering in different modes

<?php
declare(strict_types=1);

$mixed = [0, 1, '', '0', 'foo', null, false, true, []];
$onlyTruthy = array_filter($mixed);
// Result: [1=>1, 4=>'foo', 8=>true]

// Custom condition: keep only even numbers
$nums = [1,2,3,4,5,6];
$even = array_filter($nums, static fn(int $n): bool => $n % 2 === 0);
// [1=>2, 3=>4, 5=>6]

// Reindex after filtering
$evenReindexed = array_values($even); // [2,4,6]

// Filtering by key
$prices = ['apple'=>3.5,'banana'=>2.0,'avocado'=>8.0];
$onlyA = array_filter(
    $prices,
    static fn(string $key): bool => str_starts_with($key,'a'),
    ARRAY_FILTER_USE_KEY
);
// ['apple'=>3.5,'avocado'=>8.0]

// Filtering with access to key + value
$longNamedExpensive = array_filter(
    $prices,
    static fn(float $v,string $k): bool => strlen($k)>5 && $v>3,
    ARRAY_FILTER_USE_BOTH
);
// ['avocado'=>8.0]

Note: If you want to keep values equal to 0 or '0', always pass your own callback. Default filtering removes them.


arraywalk — in-place modification and side effects

<?php
declare(strict_types=1);

$data = ['name'=>'  Alice ','role'=>" ADMIN\n",'email'=>"\tuser@example.com "];

array_walk(
    $data,
    static function (&$value,$key): void {
        $value = strtolower(trim($value));
    }
);
print_r($data);
// ['name'=>'alice','role'=>'admin','email'=>'user@example.com']

// Validation + logging
$errors = [];
array_walk(
    $data,
    static function ($value,$key) use (&$errors): void {
        if ($key==='email' && !filter_var($value,FILTER_VALIDATE_EMAIL)) {
            $errors[] = "Invalid email: $value";
        }
    }
);
if ($errors) print_r($errors);


Combining map + filter vs single pass

<?php
declare(strict_types=1);

$raw = [' 10 ',' -3',' 7 ','abc',' 0 '];

// Two passes: map + filter
$ints = array_map(static fn(string $v): int => (int)trim($v), $raw);
$positive = array_filter($ints, static fn(int $n): bool => $n>0);
// [0=>10,2=>7]

// One pass: foreach (less allocation, sometimes faster)
$positiveSinglePass = [];
foreach ($raw as $v) {
    $n = (int)trim($v);
    if ($n>0) $positiveSinglePass[] = $n;
}
// [10,7]


Micro-benchmarking (illustrative only)

<?php
declare(strict_types=1);

function bench(callable $fn,int $times=5): float {
    $best=PHP_FLOAT_MAX;
    for($i=0;$i<$times;$i++){
        $start=microtime(true);
        $fn();
        $elapsed=microtime(true)-$start;
        if($elapsed<$best)$best=$elapsed;
    }
    return $best;
}

$N=200_000;
$words=array_fill(0,$N,'Example');

$mapClosure=bench(fn()=>array_map(static fn(string $v)=>strtolower($v),$words));
$mapBuiltin=bench(fn()=>array_map('strtolower',$words));

$foreachManual=bench(function()use($words){
    $out=[];
    foreach($words as $w){$out[]=strtolower($w);} return $out;
});

echo "closure:  $mapClosure\n";
echo "builtin:  $mapBuiltin\n";
echo "foreach: $foreachManual\n";


Best Practices and Common Mistakes

Best Practices

  • Use the right tool:
* array
map → transformations, returns new array. * arrayfilter → selection, keeps keys (use arrayvalues if you need reindexing). * arraywalk → in-place modifications with side effects.
  • Prefer built-in functions as callables ('trim','intval','strtolower') — often faster.
  • Use arrow functions (fn) for short logic, and mark closures static when \$this isn’t needed.
  • Be mindful of keys:
* array
filter preserves keys. * arraymap preserves keys only with one array.
  • Keep callbacks pure (no side effects) for map/filter; side effects belong in walk.
  • Profile with real profilers (Blackfire, Tideways). Don’t rely only on micro-benchmarks.

Common Mistakes

  • Forgetting that arrayfilter without callback removes 0 and '0'.
  • Expecting arrayfilter to reindex automatically (use arrayvalues).
  • Assuming arraywalk returns a new array (it doesn’t).
  • Overusing map→filter→map pipelines for huge arrays (may waste memory).
  • Using closures that capture large variables unnecessarily.
  • Ignoring strict typing in callbacks (use declare(stricttypes=1)).
---

Summary

  • arraymap: transforms elements, returns new array (preserves keys only with one input array).
  • arrayfilter: selects elements, preserves keys, default removes falsey values.
  • arraywalk: iterates with side effects, modifies in place, returns bool.
  • Performance: built-in functions are optimized, but callbacks cost. foreach may be faster for trivial work.
  • Always profile in real context before micro-optimizing.
---

Mini Quiz

    • What does arraymap return vs arraywalk? → arraymap returns new array, arraywalk returns bool (modifies in place).
    • How does arrayfilter handle keys, and when use arrayvalues? → Keeps keys, use arrayvalues to reindex.
    • How to modify values in place with arraywalk? → Pass first param by reference in callback.
    • Does arrayfilter remove 0 and '0' without callback? → Yes, because they’re falsey.
    • How to filter by keys instead of values? → Use ARRAYFILTERUSEKEY.
    • When can foreach be faster than map+filter? → With very large arrays doing trivial work.
    • What happens to keys when mapping multiple arrays? → They are reindexed numerically.
    • Which callback is faster: 'strtolower' string or closure calling strtolower? → The string, since PHP calls it directly.
---

Now you know how to use arraymap, arrayfilter, and arraywalk effectively to write faster, cleaner PHP code.

Back to Instant results from learning PHP