Php array map and filter

Sorry for the vague title, I had trouble summarizing this question in one sentence (I'm open to suggestions or edits).

I have a 2 dimensional associative array with an array of 2 numbers for each key.

Like this:

Array
   (
   [one] => Array
      (
      [0] => 1
      [1] => 2
   )
   [two] => Array
      (
      [0] => 1
      [1] => 2
   )
   [three] => Array
      (
      [0] => 1
      [1] => 2
   )
)

I'm wondering if there is a way to use array_map() or array_filter() to return an array that has each key and the first number in each of the value arrays, like this:

Array
   (
   [one] => 1
   [two] => 1
   [three] => 1
)

I do not wish to create a new array by using a loop or anything like that, I'd like to do the conversion on the fly as an argument to a function, if you know what I mean.

I could write my own function to achieve this but I'm interested in knowing if it can be done with array_map() or array_filter().

I tried using various combinations of array_merge(), array_keys() and array_values() with no success.

I thank you in advance for any help you may provide.

Edd Mann Developer

02 Mar 2016

Over the past couple of years I have transitioned from boilerplate-heavy, imperative code, to begin using the more intuitive map, filter and reduce higher-order functions. In this article I hope to highlight the transformation that occurs, along with simplification, when moving away from the imperative and onto the declarative. We shall be performing a simple process which transforms a collection of user entries into a filtered collection of their names. Although trivial in nature, it is a great place to highlight the power of the paradigm shift.

Below you will find the initial collection of user entires we wish to process. The objective is to create a function which returns only the users names, excluding however, the one associated to a supplied id.

$users = [
    [ 'id' => 1, 'name' => 'Joe' ],
    [ 'id' => 2, 'name' => 'Bob' ],
    [ 'id' => 3, 'name' => 'Sally' ],
];

Imperative Approach

Looking at this problem with an imperative mindset leads us to iterating through the collection, adding names to a temporary collection which match the desired predicate. This boilerplate code is sprinkled throughout many code-bases, and although correct, I feel can be improved upon in its intent and expression.

function getNames(array $users, $excludeId)
{
    $names = [];

    foreach ($users as $u) {
        if ($u['id'] != $excludeId) {
            $names[] = $u['name'];
        }
    }

    return $names;
}

Mapping and Filtering

The first higher-order functions we shall be using to tackle this problem are the map and filter. As their names suggests, mapping over a collection applies the given function to each of its’ elements, were as filtering returns the matching elements based on a supplied predicate function. Using these two functions we are able to break apart the problem very clearly into its two individual pieces. Unfortunately however, within PHP we do have to provide quiet verbose declarations, but the intent I feel is still more clearly highlighted.

function getNames(array $users, $excludeId)
{
    $filtered = array_filter($users, function ($u) use ($excludeId) {
        return $u['id'] != $excludeId;
    });

    return array_map(function ($u) { return $u['name']; }, $filtered);
}

Reducing

The solution above is a significant improvement in my opinion, but can be made even better with the introduction of reduce. Simply put reduce can be considered the backbone of both map and filter, as both functions can be created from it. In this instance the supplied function is applied to each of the elements in the collection. This may sound similar to a map, however the addition of an accumulator value (initial value supplied) which is supplied and returned upon each element application, allows you to craft the result you desire. Using this higher-order function provides you with far more flexibility in the resulting transformation. Were as mapping focuses on transforming individual elements, and filtering removes elements from the collection, reducing can do both and so much more.

function getNames(array $users, $excludeId)
{
    return array_reduce($users, function ($acc, $u) use ($excludeId) {
        if ($u['id'] == $excludeId) {
            return $acc;
        }

        return array_merge($acc, [ $u['name'] ]);
    }, []);
}

Again sadly PHP’s syntax leaves a lot to be desired in regard to declaration of lambda functions and immutable arrays. However, again the intent of the code to me has been significantly improved from the original imperative solution.

How to filter in array PHP?

To filter an array in PHP, use the array_filter() method. The array_filter() takes an array and filter function and returns the filtered array. The filter function is a custom user-defined function with its logic and based on that, it filters out the array values and returns them.

What is array map in PHP?

Definition and Usage. The array_map() function sends each value of an array to a user-made function, and returns an array with new values, given by the user-made function.

What exactly is the the difference between array_map Array_walk and array_filter?

The resulting array of array_map has the same length as that of the largest input array; array_walk does not return an array but at the same time it cannot alter the number of elements of original array; array_filter picks only a subset of the elements of the array according to a filtering function.

Does array map preserve keys?

The returned array will preserve the keys of the array argument if and only if exactly one array is passed. If more than one array is passed, the returned array will have sequential integer keys.