Having read this SO post, In PHP I am aware that you can get the index
under iteration with array_map
as such:
array_map(function($item, $index) { ... }, $items, array_keys($items));
How can I get the an $index
available to me when I use array_reduce
? I have tried:
array_reduce($items, array_keys($items), function($acc, $item, $index) { ... }, array());
array_reduce($items, function($acc, $item, $index) { ... }, array(), array_keys($items));
But I still can't seem to get $index
in an array_reduce
. Has anyone successfully done this before?
EDIT
Here's some context as to why I am asking this question.
I do not want to use foreach
because I would have to mutate an array outside of the foreach
in order to create my collection. I would prefer to avoid mutation.
Other languages allow one to use reduce
and get access to the current index like in JavaScript and Ruby. I was hoping to get the same feature in PHP. Oh well! Looks like I'm going to have to use a foreach
to create my array while also having the current index under iteration.
I just had same issue. It's pretty simple to solve.
$i = 0;
$p = array_reduce($array, function($output, $item) use (&$i) {
// use $i
// do something with $item and/or $output
$i++; // increment $i
return $output;
}, $initial);
&$i
pass $i
as reference and grants it will be updated.
<?php
$data = ['one', 'two', 'three'];
$result = array_reduce($data, function($carry, $item){
$carry['out'] .= $carry['i'] . ') '. $item . '; ';
$carry['i']++;
return $carry;
}, ['out' => '', 'i' => 1] )['out'];
echo $result; // 1) one; 2) two; 3) three;
Arrays in PHP are peculiar things: they can be used as lists, queues, dictionaries, sets, ordered dictionaries, and all sorts of other multi-valued structures. However, most functions are written with one or two of those structures in mind.
In the case of array_reduce
, the array is treated as a list - an ordered collection of items. As such, the keys of the array are not handed to the callback. This makes sense for common cases, like calculating a total, or an average, etc.
There are undoubtedly cases where you want to instead reduce an ordered dictionary of key-value pairs; unfortunately, PHP does not provide a function for that.
On the other hand, there are two related functions which might be usable instead:
array_map
, which runs the callback on each element and produces a new array with one item of output for item of inputarray_walk
, which runs the callback on each element and ignores the result, but which can take a third parameter by reference where side-effects can be accumulatedAll three functions can also trivially be implemented with a foreach
loop, so you could write your own reduce
function something like this (untested):
function array_reduce_assoc(array $array, callable $callback, $initial=null) {
$carry = $initial;
foreach ( $array as $key => $value ) {
$carry = $callback($carry, $key, $value);
}
return $carry;
}
You already know you how to get the index in array_map
, so you could use that to reduce instead if you like. Just use
a reference to the "carry" variable in the callback.
$example = ['a' => 1, 'b' => 2, 'c' => 3];
array_map(function($key, $value) use (&$reduced) {
$reduced .= "$key$value"; // for example
}, array_keys($example), $example);
echo $reduced; //a1b2c3
I'm not sure I see the advantage of this over foreach, but it's another possible way to do it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With