php 如何展平多维数组?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1319903/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Flatten a Multidimensional Array?
提问by Alix Axel
Is it possible, in PHP, to flatten a (bi/multi)dimensional array without using recursion or references?
在 PHP 中,是否可以在不使用递归或引用的情况下展平(双/多)维数组?
I'm only interested in the values so the keys can be ignored, I'm thinking in the lines of array_map()and array_values().
我只关心的值,这样的键可以忽略不计,我想在的线array_map()和array_values()。
回答by too much php
As of PHP 5.3the shortest solution seems to be array_walk_recursive()with the new closures syntax:
从PHP 5.3 开始,最短的解决方案似乎是array_walk_recursive()使用新的闭包语法:
function flatten(array $array) {
$return = array();
array_walk_recursive($array, function($a) use (&$return) { $return[] = $a; });
return $return;
}
回答by VolkerK
You can use the Standard PHP Library (SPL)to "hide" the recursion.
您可以使用标准 PHP 库 (SPL)来“隐藏”递归。
$a = array(1,2,array(3,4, array(5,6,7), 8), 9);
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($a));
foreach($it as $v) {
echo $v, " ";
}
prints
印刷
1 2 3 4 5 6 7 8 9
回答by Prasanth Bendra
Solution for 2 dimensional array
二维数组的解决方案
Please try this :
请试试这个:
$array = your array
$result = call_user_func_array('array_merge', $array);
echo "<pre>";
print_r($result);
EDIT : 21-Aug-13
编辑:21-Aug-13
Here is the solution which works for multi-dimensional array :
这是适用于多维数组的解决方案:
function array_flatten($array) {
$return = array();
foreach ($array as $key => $value) {
if (is_array($value)){
$return = array_merge($return, array_flatten($value));
} else {
$return[$key] = $value;
}
}
return $return;
}
$array = Your array
$result = array_flatten($array);
echo "<pre>";
print_r($result);
Ref: http://php.net/manual/en/function.call-user-func-array.php
参考:http: //php.net/manual/en/function.call-user-func-array.php
回答by Joyce Babu
In PHP 5.6 and above you can flatten two dimensional arrays with array_mergeafter unpacking the outer array with ...operator. The code is simple and clear.
在 PHP 5.6 及更高版本中,您可以array_merge在使用...运算符解压外部数组后使用扁平化二维数组。代码简单明了。
array_merge(...$a);
This works with collection of associative arrays too.
这也适用于关联数组的集合。
$a = [[10, 20], [30, 40]];
$b = [["x" => "X", "y" => "Y"], ["p" => "P", "q" => "Q"]];
print_r(array_merge(...$a));
print_r(array_merge(...$b));
Array
(
[0] => 10
[1] => 20
[2] => 30
[3] => 40
)
Array
(
[x] => X
[y] => Y
[p] => P
[q] => Q
)
But it does not work when the outer array has non numeric keys. In that case, you will have to call array_valuesfirst.
但是当外部数组有非数字键时它不起作用。在这种情况下,您必须先致电array_values。
$c = ["a" => ["x" => "X", "y" => "Y"], "b" => ["p" => "P", "q" => "Q"]];
print_r(array_merge(...array_values($c)));
Array
(
[x] => X
[y] => Y
[p] => P
[q] => Q
)
Update: Based on comment by @MohamedGharib
更新:基于@MohamedGharib 的评论
This will throw an error if the outer array is empty, since array_mergewould be called with zero arguments. It can be be avoided by adding an empty array as the first argument.
如果外部数组为空,这将引发错误,因为array_merge将使用零参数调用。可以通过添加一个空数组作为第一个参数来避免。
array_merge([], ...$a);
回答by hakre
To flatten w/o recursion (as you have asked for), you can use a stack. Naturally you can put this into a function of it's own like array_flatten. The following is a version that works w/o keys:.
要扁平化无递归(正如您所要求的),您可以使用stack。当然,您可以将其放入它自己的函数中,例如array_flatten. 以下是一个无需密钥即可工作的版本:。
function array_flatten(array $array)
{
$flat = array(); // initialize return array
$stack = array_values($array); // initialize stack
while($stack) // process stack until done
{
$value = array_shift($stack);
if (is_array($value)) // a value to further process
{
$stack = array_merge(array_values($value), $stack);
}
else // a value to take
{
$flat[] = $value;
}
}
return $flat;
}
Elements are processed in their order. Because subelements will be moved on top of the stack, they will be processed next.
元素按其顺序进行处理。因为子元素会被移到栈顶,所以接下来会处理它们。
It's possible to take keys into account as well, however, you'll need a different strategy to handle the stack. That's needed because you need to deal with possible duplicate keys in the sub-arrays. A similar answer in a related question: PHP Walk through multidimensional array while preserving keys
也可以考虑键,但是,您需要不同的策略来处理堆栈。这是必需的,因为您需要处理子数组中可能的重复键。相关问题中的类似答案:PHP Walk through multidimensional array while reserved keys
I'm not specifically sure, but I I had tested this in the past: The RecurisiveIteratordoes use recursion, so it depends on what you really need. Should be possible to create a recursive iterator based on stacks as well:
我不是特别确定,但 II 过去曾对此进行过测试:RecurisiveIterator确实使用了递归,因此这取决于您真正需要什么。也应该可以创建基于堆栈的递归迭代器:
foreach(new FlatRecursiveArrayIterator($array) as $key => $value)
{
echo "** ($key) $value\n";
}
I didn't make it so far, to implement the stack based on RecursiveIteratorwhich I think is a nice idea.
到目前为止,我还没有做到,基于RecursiveIterator我认为是一个不错的主意来实现堆栈。
回答by Allen Linatoc
Straightforwardand One-lineranswer.
简单的和一衬答案。
function flatten_array(array $array)
{
return iterator_to_array(
new \RecursiveIteratorIterator(new \RecursiveArrayIterator($array)));
}
Usage:
用法:
$array = [
'name' => 'Allen Linatoc',
'profile' => [
'age' => 21,
'favourite_games' => [ 'Call of Duty', 'Titanfall', 'Far Cry' ]
]
];
print_r( flatten_array($array) );
Output (in PsySH):
输出(在 PsySH 中):
Array
(
[name] => Allen Linatoc
[age] => 21
[0] => Call of Duty
[1] => Titanfall
[2] => Far Cry
)
Now it's pretty up to you now how you'll handle the keys. Cheers
现在由您决定如何处理这些键。干杯
EDIT(2017-03-01)
编辑(2017-03-01)
Quoting Nigel Alderton's concern/issue:
引用Nigel Alderton的担忧/问题:
Just to clarify, this preserves keys (even numeric ones) so values that have the same key are lost. For example
$array = ['a',['b','c']]becomesArray ([0] => b, [1] => c ). The'a'is lost because'b'also has a key of0
只是为了澄清,这会保留键(甚至是数字键),因此具有相同键的值将丢失。例如
$array = ['a',['b','c']]变成Array ([0] => b, [1] => c ). 将'a'被丢失,因为'b'也有一个关键0
Quoting Svish's answer:
引用Svish的回答:
Just add false as second parameter
($use_keys)to the iterator_to_arraycall
只需将 false 作为第二个参数添加
($use_keys)到iterator_to_array调用中
回答by nilamo
Uses recursion. Hopefully upon seeing how not-complex it is, your fear of recursion will dissipate once you see how not-complex it is.
使用递归。希望在看到它有多不复杂后,一旦你看到它有多不复杂,你对递归的恐惧就会消散。
function flatten($array) {
if (!is_array($array)) {
// nothing to do if it's not an array
return array($array);
}
$result = array();
foreach ($array as $value) {
// explode the sub-array, and add the parts
$result = array_merge($result, flatten($value));
}
return $result;
}
$arr = array('foo', array('nobody', 'expects', array('another', 'level'), 'the', 'Spanish', 'Inquisition'), 'bar');
echo '<ul>';
foreach (flatten($arr) as $value) {
echo '<li>', $value, '</li>';
}
echo '<ul>';
Output:
输出:
<ul><li>foo</li><li>nobody</li><li>expects</li><li>another</li><li>level</li><li>the</li><li>Spanish</li><li>Inquisition</li><li>bar</li><ul>
回答by Warbo
Just thought I'd point out that this is a fold, so array_reduce can be used:
只是想我会指出这是一个折叠,所以可以使用 array_reduce:
array_reduce($my_array, 'array_merge', array());
EDIT: Note that this can be composed to flatten any number of levels. We can do this in several ways:
编辑:请注意,这可以组合成展平任意数量的级别。我们可以通过几种方式做到这一点:
// Reduces one level
$concat = function($x) { return array_reduce($x, 'array_merge', array()); };
// We can compose $concat with itself $n times, then apply it to $x
// This can overflow the stack for large $n
$compose = function($f, $g) {
return function($x) use ($f, $g) { return $f($g($x)); };
};
$identity = function($x) { return $x; };
$flattenA = function($n) use ($compose, $identity, $concat) {
return function($x) use ($compose, $identity, $concat, $n) {
return ($n === 0)? $x
: call_user_func(array_reduce(array_fill(0, $n, $concat),
$compose,
$identity),
$x);
};
};
// We can iteratively apply $concat to $x, $n times
$uncurriedFlip = function($f) {
return function($a, $b) use ($f) {
return $f($b, $a);
};
};
$iterate = function($f) use ($uncurriedFlip) {
return function($n) use ($uncurriedFlip, $f) {
return function($x) use ($uncurriedFlip, $f, $n) {
return ($n === 0)? $x
: array_reduce(array_fill(0, $n, $f),
$uncurriedFlip('call_user_func'),
$x);
}; };
};
$flattenB = $iterate($concat);
// Example usage:
$apply = function($f, $x) {
return $f($x);
};
$curriedFlip = function($f) {
return function($a) use ($f) {
return function($b) use ($f, $a) {
return $f($b, $a);
}; };
};
var_dump(
array_map(
call_user_func($curriedFlip($apply),
array(array(array('A', 'B', 'C'),
array('D')),
array(array(),
array('E')))),
array($flattenA(2), $flattenB(2))));
Of course, we could also use loops but the question asks for a combinator function along the lines of array_map or array_values.
当然,我们也可以使用循环,但问题要求沿 array_map 或 array_values 行的组合器函数。
回答by artnikpro
Flattens two dimensional arrays only:
仅展平二维数组:
$arr = [1, 2, [3, 4]];
$arr = array_reduce($arr, function ($a, $b) {
return array_merge($a, (array) $b);
}, []);
// Result: [1, 2, 3, 4]
回答by too much php
This solution is non-recursive. Note that the order of the elements will be somewhat mixed.
此解决方案是非递归的。请注意,元素的顺序会有些混乱。
function flatten($array) {
$return = array();
while(count($array)) {
$value = array_shift($array);
if(is_array($value))
foreach($value as $sub)
$array[] = $sub;
else
$return[] = $value;
}
return $return;
}

