-
-
Save SeanCannon/6585889 to your computer and use it in GitHub Desktop.
<?php | |
/** | |
* Convert a multi-dimensional array into a single-dimensional array. | |
* @author Sean Cannon, LitmusBox.com | seanc@litmusbox.com | |
* @param array $array The multi-dimensional array. | |
* @return array | |
*/ | |
function array_flatten($array) { | |
if (!is_array($array)) { | |
return false; | |
} | |
$result = array(); | |
foreach ($array as $key => $value) { | |
if (is_array($value)) { | |
$result = array_merge($result, array_flatten($value)); | |
} else { | |
$result = array_merge($result, array($key => $value)); | |
} | |
} | |
return $result; | |
} |
Here is what I was looking for:
function true_flatten(array $array, array $parents = [])
{
$return = [];
foreach ($array as $k => $value) {
$p = empty($parents) ? [$k] : [...$parents, $k];
if (is_array($value)) {
$return = [...$return, ...true_flatten($value, $p)];
} else {
$return[implode('_', $p)] = $value;
}
}
return $return;
}
Sample array:
$r = [
'a' => 'value1',
'b' => [
'c' => 'value1.1',
'd' => 'value1.2',
],
'e' => 'value2',
'f' => [
'j' => [
'k' => 'value2.1',
'm' => 'value2.2',
'n' => 'value2.3',
],
],
'o' => 'value3',
'p' => [
'some' => [
'very' => [
'deep' => [
'item' => [
'first',
'second',
]
]
]
]
],
'q' => 'value5',
]; // sample data
Output:
{
"a": "value1",
"b_c": "value1.1",
"b_d": "value1.2",
"e": "value2",
"f_j_k": "value2.1",
"f_j_m": "value2.2",
"f_j_n": "value2.3",
"o": "value3",
"p_some_very_deep_item_0": "first",
"p_some_very_deep_item_1": "second",
"q": "value5"
}
Nice @graceman9, but it doesn't work in PHP 7, as unpacking arrays with string keys was only implemented in PHP 8.
Fatal error: Uncaught Error: Cannot unpack array with string keys
Ref: https://wiki.php.net/rfc/array_unpacking_string_keys
I just changed ...
with array_merge
to make your code compatible with older versions of PHP.
function true_flatten(array $array, array $parents = [])
{
$return = [];
foreach ($array as $k => $value) {
$p = empty($parents) ? [$k] : array_merge($parents, [$k]);
if (is_array($value)) {
$return = array_merge($return, true_flatten($value, $p));
} else {
$return[implode('_', $p)] = $value;
}
}
return $return;
}
Output:
Array
(
[a] => value1
[b_c] => value1.1
[b_d] => value1.2
[e] => value2
[f_j_k] => value2.1
[f_j_m] => value2.2
[f_j_n] => value2.3
[o] => value3
[p_some_very_deep_item_0] => first
[p_some_very_deep_item_1] => second
[q] => value5
)
Tested in PHP 7.4.9
@sayhicoelho Have you tried my approach above? It should work with associative and non-associative arrays, and be compatible with PHP 7+.
It also supports a depth parameter, so you can easily flatten only the top layer, the first N layers, or infinitely.
@brandonmcconnell Using my sample data it gives not what I expected.
By the way, how to use it with unlimited $depth? array_flatten($r, 999)
doesn't look good for me
Despite of that your function does the job of flattening, no doubt :) maybe flatten is not the right word because of ambiguity?
@sayhicoelho thanks for 7.x support!
echo json_encode(array_flatten($r, 9));
{
"a": "value1",
"c": "value1.1",
"d": "value1.2",
"e": "value2",
"k": "value2.1",
"m": "value2.2",
"n": "value2.3",
"o": "value3",
"0": "first",
"1": "second",
"q": "value5"
}
@graceman9 What data produces an unexpected result?
For infinite depth, just use -1
@brandonmcconnell Have you noticed the difference?
{
"a": "value1",
"b_c": "value1.1",
}
and
{
"a": "value1",
"c": "value1.1",
}
@graceman9 Oh you want the keys to be concatenated, so every key keeps the log of its original path. Yeah, you are correct that my version does not do that. I tried to follow the approach common in other languages. 🙂
For a simple 2D array:
$multiDimArray = [[1, 2], [3, 4], [5, 6]];
$flatArray = array_reduce($multiDimArray, 'array_merge', []);
Working with associative arrays:
Using