它是可能的,在PHP中,在不使用递归或引用的情况下扁平化(bi/multi)维数组?
我只对值感兴趣,所以键可以忽略,我认为在array_map()和array_values()的行。
它是可能的,在PHP中,在不使用递归或引用的情况下扁平化(bi/multi)维数组?
我只对值感兴趣,所以键可以忽略,我认为在array_map()和array_values()的行。
当前回答
如果你想保住你的钥匙,那就是解决办法。
function flatten(array $array) {
$return = array();
array_walk_recursive($array, function($value, $key) use (&$return) { $return[$key] = $value; });
return $return;
}
不幸的是,它只输出最后的嵌套数组,没有中间键。对于下面的例子:
$array = array(
'sweet' => array(
'a' => 'apple',
'b' => 'banana'),
'sour' => 'lemon');
print_r(flatten($fruits));
输出是:
Array
(
[a] => apple
[b] => banana
[sour] => lemon
)
其他回答
使用递归生成器怎么样?https://ideone.com/d0TXCg
<?php
$array = [
'name' => 'Allen Linatoc',
'profile' => [
'age' => 21,
'favourite_games' => [ 'Call of Duty', 'Titanfall', 'Far Cry' ]
]
];
foreach (iterate($array) as $item) {
var_dump($item);
};
function iterate($array)
{
foreach ($array as $item) {
if (is_array($item)) {
yield from iterate($item);
} else {
yield $item;
}
}
}
为了平摊w/o递归(正如您所要求的那样),您可以使用堆栈。当然,你可以把它放到自己的函数中,比如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
{
array_unshift($stack, ...$value);
}
else // a value to take
{
$flat[] = $value;
}
}
return $flat;
}
元素按顺序处理。因为子元素将被移动到堆栈的顶部,所以它们将被下一步处理。
也可以考虑键,但是,您需要不同的策略来处理堆栈。这是必需的,因为您需要处理子数组中可能重复的键。在一个相关的问题中有一个类似的答案:PHP遍历多维数组,同时保留键
我不是特别确定,但我在过去测试过这个:RecurisiveIterator确实使用递归,所以它取决于你真正需要什么。应该可以创建一个基于堆栈的递归迭代器:
foreach(new FlatRecursiveArrayIterator($array) as $key => $value)
{
echo "** ($key) $value\n";
}
Demo
到目前为止,我还没有实现基于RecursiveIterator的堆栈,我认为这是一个很好的想法。
您可以使用标准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, " ";
}
打印
1 2 3 4 5 6 7 8 9
在PHP 5.6及以上版本中,你可以使用array_merge将二维数组平直,然后使用…操作符。代码简单明了。
array_merge(...$a);
这也适用于关联数组的集合。
$a = [[10, 20], [30, 40]];
$b = [["x" => "A", "y" => "B"], ["y" => "C", "z" => "D"]];
print_r(array_merge(...$a));
print_r(array_merge(...$b));
Array
(
[0] => 10
[1] => 20
[2] => 30
[3] => 40
)
Array
(
[x] => A
[y] => C
[z] => D
)
在PHP 8.0及以下版本中,当外部数组具有非数字键时,数组解包将不起作用。PHP 8.1支持用字符串键解包数组。要支持8.0及以下版本,应该首先调用array_values。
$c = ["a" => ["x" => "A", "y" => "B"], "b" => ["y" => "C", "z" => "D"]];
print_r(array_merge(...array_values($c)));
Array
(
[x] => A
[y] => C
[z] => D
)
更新:基于@ mohammedgharib的评论(适用于PHP 7.3。X和旧的ref)
如果外层数组为空,这将抛出一个错误,因为调用array_merge时参数为零。可以通过添加一个空数组作为第一个参数来避免这种情况。
array_merge([], ...$a);
如果你有一个对象数组,想用一个节点把它压平,只需要使用这个函数:
function objectArray_flatten($array,$childField) {
$result = array();
foreach ($array as $node)
{
$result[] = $node;
if(isset($node->$childField))
{
$result = array_merge(
$result,
objectArray_flatten($node->$childField,$childField)
);
unset($node->$childField);
}
}
return $result;
}