I need to iterate over an array that looks like this:
$myArray = array(
'key1' => array('subkey' => 'subvalue'),
'key2' => array('subkey' => 'subvalue'),
)
Into each nested associative array, I want to add a key-value pair based on the outside key, like this:
$myNewArray = array(
'key1' => array('subkey' => 'subvalue', 'newkey' => 'only for key1'),
'key2' => array('subkey' => 'subvalue'),
)
Ideally, I'm looking for something like:
$myNewArray = array_map(function($key, $value) {
if ($key == 'key1') {
$value['newkey'] = 'only for key1';
}
return $value;
}, $myArray);
However, that obviously doesn't work as callback
isn't given two parameters but only one. I could do something like this:
$myNewArray = array_map(function($key, $value) {
if ($key == 'key1') {
$value['newkey'] = 'only for key1';
}
return WHAT??
}, array_keys($myArray), $myArray);
However, what do I return here? It seems to always construct a new array, i.e. discarding my string keys (key1
and key2
), while a single-array array_map()
keeps them.
I can use array_walk()
but it has a rather strange API (flipped parameter order, array passed by reference etc.) so I would generally prefer if this could be achieved using array_map()
. Can it?
I'm afraid array_walk()
IS the way to do this.
If you don't like array_walk()
and insist on doing it with array_map()
, well, it's possible. It involves using also array_keys()
, array_values()
and array_combine()
, it is long and ugly but doable:
$myNewArray = array_combine(
array_keys($myArray),
array_map(
function($key, $value) {
if ($key == 'key1') {
$value['newkey'] = 'only for key1';
}
return $value;
},
array_keys($myArray),
array_values($myArray) // can omit array_values() and use $myArray
)
);
You can also do it using array_reduce()
but it's the same mess:
$myNewArray = array_reduce(
array_keys($myArray),
function (array $carry, $key) use ($myArray) {
$value = $myArray[$key];
if ($key == 'key1') {
$value['newkey'] = 'only for key1';
}
$carry[$key] = $value;
return $carry;
},
array()
);
I hope you have a condition more complex than $key == 'key1'
because only for this it is not worth it writing complex traversal. Isn't it easier to just access the right element and modify it?
$myArray['key1']['newkey'] = 'only for key1';