使用多个叶节点展平数组的最佳方法是什么,以便每个完整的leaf路径都是一个独特的返回?
array("Object"=>array("Properties"=>array(1, 2)));
产生
我能够展平到Object.Properties.1但是2不会被递归函数处理:
function flattenArray($prefix, $array)
{
$result = array();
foreach ($array as $key => $value)
{
if (is_array($value))
$result = array_merge($result, flattenArray($prefix . $key . '.', $value));
else
$result[$prefix . $key] = $value;
}
return $result;
}
我认为自上而下在预期多个叶子节点时不起作用,所以要么需要某种类型的自下而上处理,要么为每个叶子和进程复制数组(尽管这看起来效率很低)
答案 0 :(得分:2)
function flatten(array $data, $separator = '.') {
$result = array();
$stack = array();
$path = null;
reset($data);
while (!empty($data)) {
$key = key($data);
$element = $data[$key];
unset($data[$key]);
if (is_array($element)) {
if (!empty($data)) {
$stack[] = array($data, $path);
}
$data = $element;
$path .= $key . $separator;
} else {
$result[$path . $key] = $element;
}
if (empty($data) && !empty($stack)) {
list($data, $path) = array_pop($stack);
}
}
return $result;
}
var_dump(flatten(array("Object"=>array("Properties"=>array(1, 2)))));
输出:
array(2) {
["Object.Properties.0"]=>
int(1)
["Object.Properties.1"]=>
int(2)
}
答案 1 :(得分:1)
使用Kdyby Framework中的函数flatMapAssoc():
$flattened= array();
flatMapAssoc($array, function ($value, $keys) use (&$flattened) {
$flattened[implode('.', $keys)] = $value;
});
/**
* @param array|\Traversable $array
* @param callable $callback
* @return array
*/
function flatMapAssoc($array, $callback)
{
$callback = callback($callback);
$result = array();
$walker = function ($array, $keys = array()) use (&$walker, &$result, $callback) {
foreach ($array as $key => $value) {
$currentKeys = $keys + array(count($keys) => $key);
if (is_array($value)) {
$walker($value, $currentKeys);
continue;
}
$result[] = $callback($value, $currentKeys);
}
return $result;
};
return $walker($array);
}
答案 2 :(得分:1)
我会使用包装函数来隐藏实现细节(前缀参数)
并添加了一个if分支来测试空数组。最后,如果是简单的叶子,你应该使用$value
变量,而不是$key
变量。
$x = array("Object"=>array("Properties"=>array(1, 2), "test"=>array(), "post"));
function flatten ($array) {
return flattenArray('',$array);
}
function flattenArray($prefix, $array) {
$result = array();
foreach ($array as $key => $value) {
if (is_array($value)) {
if(count($value)) {
$result = array_merge($result, flattenArray($prefix."$key.", $value));
} else {
$result[] = "$prefix$key";
}
} else {
$result[] = "$prefix$value";
}
}
return $result;
}
echo join("\n", flatten($x));
如果要模仿树结构,也许可以使用不同的数组结构。像这样:
$y = array ("Object",
array("Properties", 1, 2),
"test",
"post"
);
和flattenArray成为:
function flattenArray($prefix, $array) {
$result = array();
$prefix .=array_shift($array).'.';
foreach ($array as $value) {
if (is_array($value)) {
$result = array_merge($result, flattenArray($prefix, $value));
} else {
$result[] = "$prefix$value";
}
}
return $result;
}