具有多个叶节点的PHP Flatten Array

时间:2012-09-06 21:29:02

标签: php multidimensional-array

使用多个叶节点展平数组的最佳方法是什么,以便每个完整的leaf路径都是一个独特的返回?

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

产生

  1. Object.Properties.1
  2. Object.Properties.2
  3. 我能够展平到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;
    }
    

    我认为自上而下在预期多个叶子节点时不起作用,所以要么需要某种类型的自下而上处理,要么为每个叶子和进程复制数组(尽管这看起来效率很低)

3 个答案:

答案 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;
}