它是可能的,在PHP中,在不使用递归或引用的情况下扁平化(bi/multi)维数组?
我只对值感兴趣,所以键可以忽略,我认为在array_map()和array_values()的行。
它是可能的,在PHP中,在不使用递归或引用的情况下扁平化(bi/multi)维数组?
我只对值感兴趣,所以键可以忽略,我认为在array_map()和array_values()的行。
当前回答
试试下面这个简单的函数:
function _flatten_array($arr) {
while ($arr) {
list($key, $value) = each($arr);
is_array($value) ? $arr = $value : $out[$key] = $value;
unset($arr[$key]);
}
return (array)$out;
}
所以从这里:
array (
'und' =>
array (
'profiles' =>
array (
0 =>
array (
'commerce_customer_address' =>
array (
'und' =>
array (
0 =>
array (
'first_name' => 'First name',
'last_name' => 'Last name',
'thoroughfare' => 'Address 1',
'premise' => 'Address 2',
'locality' => 'Town/City',
'administrative_area' => 'County',
'postal_code' => 'Postcode',
),
),
),
),
),
),
)
你会得到:
array (
'first_name' => 'First name',
'last_name' => 'Last name',
'thoroughfare' => 'Address 1',
'premise' => 'Address 2',
'locality' => 'Town/City',
'administrative_area' => 'County',
'postal_code' => 'Postcode',
)
其他回答
非递归,非基于引用的实现,这可能比基于递归的实现更容易理解。 可以管理任意深度多维数组,不能平化关联数组。 它的工作原理是每个周期将数组压平一层,直到它完全有效。
function array_flatten(): array{
$result = func_get_args();
// check all elements of $list are not arrays
$_is_flat = function (array $list): bool {
foreach ($list as $val) {
if (is_array($val)) {
return false;
}
}
return true;
};
do {
$tmp = [];
foreach ($result as $val) {
if (is_array($val)) {
if (!array_is_list($val)) {
throw new \Exception(sprintf("array_flatten can't handle associative arrays: %s", json_encode($val)));
}
$tmp = array_merge($tmp, $val);
} else {
$tmp[] = $val;
}
}
$result = $tmp;
} while (!$_is_flat($result));
return $result;
}
以下是它处理的情况:
assertEquals(array_flatten(1, 2), $expected = [1, 2], 'array_flatten 1a');
assertEquals(array_flatten([1], [2]), $expected = [1, 2], 'array_flatten 1b');
assertEquals(array_flatten([1], [[2], 3]), $expected = [1, 2, 3], 'array_flatten 1c');
assertEquals(array_flatten(1, [2, 3], [4, 5]), $expected = [1, 2, 3, 4, 5], 'array_flatten 2');
assertEquals(array_flatten(2, 3, [4, 5], [6, 7], 8), $expected = [2, 3, 4, 5, 6, 7, 8], 'array_flatten 3');
assertEquals(array_flatten([2, 3, [4, 5], [6, 7], 8]), $expected = [2, 3, 4, 5, 6, 7, 8], 'array_flatten 4');
assertEquals(array_flatten([2, [3, [4, [5]], [6, [7]], 8]]), $expected = [2, 3, 4, 5, 6, 7, 8], 'array_flatten complex');
这个解是非递归的。注意,元素的顺序会有些混合。
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;
}
使用递归。希望在看到它有多简单的时候,你对递归的恐惧会在你看到它有多简单的时候消失。
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>';
输出:
<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>
简单明了的回答。
function flatten_array(array $array)
{
return iterator_to_array(
new \RecursiveIteratorIterator(new \RecursiveArrayIterator($array)));
}
用法:
$array = [
'name' => 'Allen Linatoc',
'profile' => [
'age' => 21,
'favourite_games' => [ 'Call of Duty', 'Titanfall', 'Far Cry' ]
]
];
print_r( flatten_array($array) );
输出(在PsySH):
Array
(
[name] => Allen Linatoc
[age] => 21
[0] => Call of Duty
[1] => Titanfall
[2] => Far Cry
)
现在就看你怎么处理钥匙了。干杯
编辑(2017-03-01)
引用Nigel Alderton的担忧/问题:
澄清一下,这保留了键(甚至是数字键),因此具有相同键的值将丢失。例如数组美元= [a, [' b ', ' c ']]成为数组([0]= > b, c[1] = >)。“a”丢失了,因为“b”也有一个键值为0
引用Svish的回答:
只需将false作为第二个参数($use_keys)添加到iterator_to_array调用中
我只是想指出这是一个折叠,所以可以使用array_reduce
array_reduce($my_array, 'array_merge', array());
编辑:注意,这可以组成平任意数量的水平。我们可以通过以下几种方式做到这一点:
// 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))));
当然,我们也可以使用循环,但这个问题要求的是一个组合子函数,类似于array_map或array_values。