Mapping and Filtering Arrays in PHP

#tech - 3 Minute Read

a grid of red lights on a black surface

Working with data sets in any programming language can get messy, certainly in PHP.

But even for more general-purpose languages like Python, code complexity is still a challenge. This is mainly because new programmers are accustomed to creating for-loops to process arrays. This can lead to messy code containing many nested loops, each performing different functions, often requiring incrementing counters to keep track of everything. This code becomes less and less readable.

A codebase can be more straightforward and maintainable by using functions that support callbacks, such as array_map and array_filter.

I tend to think of these two functions somewhat as opposites. Working with one list (or "column") of data, mapping means to translate each value into another value. Filtering instead makes a new, reduced list but leaves the values unchanged.

The functions that handle the actual logic of the mapping and filtering are the callback functions. Here, we place these functions directly into the callback argument, meaning they're "anonymous" functions. In more complex applications, these would more likely be written elsewhere and called by name.

array_map()

First, we get the first letter of each word.

$arr = ['apple', 'carrot', 'pear', 'pea'];

$arr_mapped = array_map(function ($string) {
    return $string[0];
}, $arr);

print_r($arr_mapped);
Array
(
    [0] => a
    [1] => c
    [2] => p
    [3] => p
)

array_filter()

Next, we reduce the array to only those words that begin with p:

$arr = ['apple', 'carrot', 'pear', 'pea'];

$arr_filtered = array_filter($arr, function ($string) {
    return $string[0] === 'p';
});

print_r($arr_filtered);
Array
(
    [2] => pear
    [3] => pea
)

The "use" keyword

The use keyword allows us to bring outside variables into the callback:

$starts_with = 'a';

$arr_filtered = array_filter($arr, function ($string) use ($starts_with) {
    return $string[0] === $starts_with;
});

print_r($arr_filtered);
Array
(
    [0] => apple
)

It may be confusing that the two functions accept the array and the callback arguments in the opposite order. This is because array_filter can be used without a callback, in which case it would filter any items whose boolean value is FALSE. This is useful for quickly removing empty values from an array before passing it onto another function.

$arr = ['apple', 'carrot', 'pear', '', 'pea'];

$arr_filtered = array_filter($arr);

print_r($arr_filtered);
Array
(
    [0] => apple
    [1] => carrot
    [2] => pear
    [4] => pea
)

Still, it's best to use array_filter with a callback, as you'll have more explicit control over exactly what values are left out.

In general, if a for-loop can't be finished in one sitting, it's too complex and probably shouldn't be a loop at all. Try using callbacks to clarify your code.


Updated May 22, 2020.