The problem:

Given an array of numbers, create a new array containing only the odd numbers from the original.

$original_array = [1,2,3,4,5,6,7,8,9,10];

There are two ways you can approach this problem. Let’s look at a foreach loop first:

$original_array = [1,2,3,4,5,6,7,8,9,10];

$odd_array = array();

foreach($original_array as $this_number){
   if(!$this_number % 2){
       $odd_array[] = $this_number;
   }
}
  1. Set up a variable to hold the new array of odd numbers.
  2. Loop over the original array
  3. Test each value – if it is not evenly divisible, push it onto the odd number array

This way of approaching the problem works, and there is nothing wrong with doing it this way. However, there is another way.

$original_array = [1,2,3,4,5,6,7,8,9,10];

$odd_array = array_filter($original_array, function($number){
     return !($number % 2);
});

The array_filter function automatically iterates over all the elements of the array. One by one, each item in the array is passed to the callback function. The array_filter function will return an array, and expects the callback to return true or false for each item. True means that item will be placed into the array that array_filter returns. False means that item won’t be in the returned array.

Inside the callback in this example, each item is tested to see if it is even, and then that result is negated because we actually want to test for odd.

The callback does not have to be inline.  You can call an external function, like this:

$original_array = [1,2,3,4,5,6,7,8,9,10];

$odd_array = array_filter($original_array, "isOdd");

function isOdd($number){
     return !($number % 2);
}

This is nice because you can separate concerns. You can now refactor the isOdd method if you want to, and it will still work.

$original_array = [1,2,3,4,5,6,7,8,9,10];

$odd_array = array_filter($original_array, "isOdd");

function isOdd($number){
     return ($number & 1);
}

Sample output: (note that array keys are preserved)

Array
(
    [0] => 1
    [2] => 3
    [4] => 5
    [6] => 7
    [8] => 9
)

 

So, what about associative arrays?

Let’s first adapt the original foreach solution:

$original_array = [

    'Cars' => ['Chevy','Ford','Toyota','Honda'],
    'Colors' => ['Blue','Red','Green','Yellow'],
    'Animals' => ['Dog','Cat','Cow','Coyote']

];

$color_array = array();

foreach($original_array as $this_key => $this_value){
   if($this_key == 'Colors'){
       $color_array[] = $this_value;
   }
}
print_r($color_array);

This will output:

Array
(
    [0] => Array
        (
            [0] => Blue
            [1] => Red
            [2] => Green
            [3] => Yellow
        )

)

Let’s try it with the array_filter function:

$original_array = [

    'Cars' => ['Chevy','Ford','Toyota','Honda'],
    'Colors' => ['Blue','Red','Green','Yellow'],
    'Animals' => ['Dog','Cat','Cow','Coyote']

];

$color_array = array_filter($original_array, function($value, $key){
     return $key === 'Colors';
}, ARRAY_FILTER_USE_BOTH);

print_r($color_array);

This will be the output:

Array
(
    [Colors] => Array
        (
            [0] => Blue
            [1] => Red
            [2] => Green
            [3] => Yellow
        )

Notice how it returns an associative array. This is different than the previous way, which had a key of [0], and may be more useful in some situations.

foreach vs array_filter