1

将具有多个叶节点的数组展平以使每个叶的完整路径都是不同的返回的最佳方法是什么?

array("Object"=>array("Properties"=>array(1, 2)));

屈服

  1. 对象.属性.1
  2. 对象.属性.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;
}

我认为在预期多个叶节点时自上而下将不起作用,因此要么需要某种类型的自下而上处理,要么需要一种为每个叶和进程复制数组的方法(尽管这似乎完全低效)

4

3 回答 3

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)
}
于 2012-09-06T22:00:48.193 回答
1

使用Kdyby 框架中的函数 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);
}
于 2012-09-06T21:34:07.827 回答
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;
}
于 2012-09-06T22:37:52.570 回答