{DEV IN LOOP

<-

array_reduce notes

This one has a simple explanation, but I find it hard to find a scenario to use it. Let's say I want to sum all the elements in an array, I need to go through all the items and pass the function sum, carrying the result from the sum before, so I end up with the resulting number.
It looks like this:

function myfunction($v1,$v2) {
    return $v1 + $v2;
}
$a=[1,2,3];
print_r(array_reduce($a,"myfunction"));//6

It's an obvious choice for an arithmetic calculation, and I could not think of just one number but reduce over a matrix that returns a new matrix with the calculated results.

$arr = [
    ['min' => 1.5456, 'max' => 2.28548, 'volume' => 23.152],
    ['min' => 1.5457, 'max' => 2.28549, 'volume' => 23.152],
    ['min' => 1.5458, 'max' => 2.28550, 'volume' => 23.152],
    ['min' => 1.5459, 'max' => 2.28551, 'volume' => 23.152],
    ['min' => 1.5460, 'max' => 2.28552, 'volume' => 23.152],
];

$initial = array_shift($arr);

$t = array_reduce($arr, function($result, $item) {
    $result['min'] = min($result['min'], $item['min']);
    $result['max'] = max($result['max'], $item['max']);
    $result['volume'] += $item['volume'];

    return $result;
}, $initial);

//this results in ["min"=> 1.5456, "max"=> 2.28552, "volume"=> 115.76]

Or to calculate the frequency of an element in a list...
But I don't encounter many of those. Where else to use it? Anything that starts with many pieces and ends up in one, even if somehow transformed. A pile of small notes that get merged in an article. A list of items that need markup:

function listOfItems($html, $p) {
    $html .= "<li><a href=\"$p.html\">$p</a></li>\n";
    return $html;
}

$list = ["page1", "page2", "page3"];

$li = array_reduce($list, "listOfItems");
echo "<ul>\n".$li . "</ul>\n";

//will echo...
<ul>
<li><a href="page1.html">page1</a></li>
<li><a href="page2.html">page2</a></li>
<li><a href="page3.html">page3</a></li>
</ul>

Taking it further one can pass functions to the array_reduce in the stack:

$f1 = function($x, $f) {
    echo 'middleware 1 begin with value: '. $x .PHP_EOL;
    $x += 1;
    $x = $f($x);
    echo 'middleware 1 end.'.PHP_EOL;
    echo 'and returns:'.$x .PHP_EOL;
    return $x;    
};

$f2 = function($x, $f) {
    echo 'middleware 2 begin with value: '. $x .PHP_EOL;
    $x += 2;
    $x = $f($x);
    echo 'middleware 2 end.'.PHP_EOL;
    echo 'and returns:'.$x .PHP_EOL;
    return $x;
};

$f3 = function($x, $f) {
    echo 'middleware 3 begin with value: '. $x .PHP_EOL;
    $x += 3;
    $x = $f($x);
    echo 'middleware 3 end.'.PHP_EOL;
    echo 'and returns:'.$x .PHP_EOL;
    return $x;
};

$respond = function($x) {
    echo 'Generate some response.'.PHP_EOL;
    return $x;
};

$middlewares = [$f1, $f2, $f3];
$initial = $respond;
$foo = array_reduce($middlewares, function($stack, $item) {
        return function($request) use ($stack, $item){
            echo "Passing the param with value ". $request.PHP_EOL;
            return $item($request, $stack);
        };
}, $initial);

$x = 1;
echo $foo($x);

I wanted to see the order of the calls. If I pass functions to the reduce in the stack, it will process them in inverse order, pass along the value as expected, and then return one number. So, in this case, I can use it to apply some transformations to the object and maybe return a success.

Passing the param with value 1
middleware 3 begin with value: 1
Passing the param with value 4
middleware 2 begin with value: 4
Passing the param with value 6
middleware 1 begin with value: 6
Generate some response.
middleware 1 end. and returns:7
middleware 2 end. and returns:7
middleware 3 end. and returns:7
7

Bit lengthy, but now it seems straightforward. Next time we go for a walk!

  • array_reduce notes
  • Carmen Maymó