I'd been using this form for a while now with the functional methods map, filter, reduce:
// For example...
$result = array_reduce(array_map(function($value) {
return explode('-', $value);
}, $input), function($carry, $item) {
return array_merge($carry, $item);
}, array());
The array_reduce()
part, where I need to collapse depth in the result. So I was thinking about this, and this is what I came up with. It actually works as a callback to array_reduce()
too:
/**
* Flatten a multi-dimensional array to a single-level array,
* sorting the entries in order to depth first.
*
* @param array $carry Array to initialize, will be the subject if the only argument passed.
* @param mixed $subject Optional Array or value that has data in potential multi-dimensions.
*
* @return array
*/
function array_flatten(?array $carry = [], $subject = null): array
{
return array_reduce((array) ($subject ?? $carry), function(array $carry, $item) {
return is_array($item)
? array_flatten($carry, $item)
: array_merge($carry, (array) $item);
}, $subject !== null ? (array) $carry : []); // Don't merge onto the $subject...
}
Thing is, the way it works, I think it literally goes one level further than there are levels to traverse. The reason I think this is because the array_merge()
is getting passed a "boxed" element. So the way I'm adding to the array is to box/unbox an array wrapper so it can be merged.
That seems like the most amount of extra effort for one little thing; it happens to every non-array it comes across. Questioning whether I should use it.
It can be called like array_reduce()
:
array_reduce([1,2,[3,[4]],5], 'array_flatten');
Or more likely:
array_flatten([1,2,[3,[4]],5]);
Is this something I should avoid?