PHP : flatten array - fastest way? [duplicate]
Is there any fast way to flatten an array and select subkeys ('key'&'value' in this case) without running a foreach loop, or is the foreach always the fastest way?
Array
(
[0] => Array
(
[key] => string
[value] => a simple string
[cas] => 0
)
[1] => Array
(
[key] => int
[开发者_JAVA技巧value] => 99
[cas] => 0
)
[2] => Array
(
[key] => array
[value] => Array
(
[0] => 11
[1] => 12
)
[cas] => 0
)
)
To:
Array
(
[int] => 99
[string] => a simple string
[array] => Array
(
[0] => 11
[1] => 12
)
)
Give this a shot:
$ret = array();
while ($el = each($array)) {
$ret[$el['value']['key']] = $el['value']['value'];
}
call_user_func_array("array_merge", $subarrays)
can be used to "flatten" nested arrays.
What you want is something entirely different. You could use array_walk()
with a callback instead to extract the data into the desired format. But no, the foreach loop is still faster. There's no array_*
method to achieve your structure otherwise.
Hopefully it will help someone else, but here is a function I use to flatten arrays and make nested elements more accessible.
Usage and description here: https://totaldev.com/flatten-multidimensional-arrays-php/
The function:
// Flatten an array of data with full-path string keys
function flat($array, $separator = '|', $prefix = '', $flattenNumericKeys = false) {
$result = [];
foreach($array as $key => $value) {
$new_key = $prefix . (empty($prefix) ? '' : $separator) . $key;
// Make sure value isn't empty
if(is_array($value)) {
if(empty($value)) $value = null;
else if(count($value) == 1 && isset($value[0]) && is_string($value[0]) && empty(trim($value[0]))) $value = null;
}
$hasStringKeys = is_array($value) && count(array_filter(array_keys($value), 'is_string')) > 0;
if(is_array($value) && ($hasStringKeys || $flattenNumericKeys)) $result = array_merge($result, flat($value, $separator, $new_key, $flattenNumericKeys));
else $result[$new_key] = $value;
}
return $result;
}
This should properly combine arrays with integer keys. If the keys are contiguous and start at zero, they will be dropped. If an integer key doesn't yet exist in the flat array, it will be kept as-is; this should mostly preserve non-contiguous arrays.
function array_flatten(/* ... */)
{
$flat = array();
array_walk_recursive(func_get_args(), function($value, $key)
{
if (array_key_exists($key, $flat))
{
if (is_int($key))
{
$flat[] = $value;
}
}
else
{
$flat[$key] = $value;
}
});
return $flat;
}
You could use !isset($key)
or empty($key)
instead to favor useful values.
Here's a more concise version:
function array_flatten(/* ... */)
{
$flat = array();
array_walk_recursive(func_get_args(), function($value, $key) use (&$flat)
{
$flat = array_merge($flat, array($key => $value));
});
return $flat;
}
精彩评论