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ó