在PHP中从多维数组构建路径

7

我有一个数组,例如:

$tree = array(
    'folder_1' => array(
        'folder_1_1',
        'folder_1_2' => array(
            'folder_1_2_1',
            'folder_1_2_2'
        ),
        'folder_1_3'
    ),
    'folder_2' => array(
        'folder_2_1' => array(
            'folder_2_1_1' => array(
                'folder_2_1_1_1',
                'folder_2_1_1_2'
            )
        ),
    )
);

我正在尝试创建一个路径数组:

$paths = array(
    'folder_1',
    'folder_1/folder_1_1',
    'folder_1/folder_1_2',
    'folder_1/folder_1_2/folder_1_2_1',
    'folder_1/folder_1_2/folder_1_2_2',
    'folder_2',
    'folder_2/folder_2_1',
    ...
);

我似乎找不到实现这个的方法。我遇到的问题是文件夹名称既可以作为数组键,也可以作为数组元素。

目前为止,我已经做了以下工作,但离解决方案还很远...

$paths = transform_tree_to_paths($trees);

function transform_tree_to_paths($trees, $current_path = '', $paths = array())
{

    if (is_array($trees)) {
        foreach ($trees as $tree => $children) {
            $current_path .= $tree . '/';
            return transform_tree_to_paths($children, $current_path, $paths);
        }
        $paths[] = $current_path;
        $current_path = '';
    } else {
        $paths[]  = $trees;
    }

    return $paths;
}
2个回答

10

这个怎么样?

function gen_path($tree, $parent=null) {
    $paths = array();

    //add trailing slash to parent if it is not null
    if($parent !== null) {
        $parent = $parent.'/';
    }

     //loop through the tree array
     foreach($tree as $k => $v) {
        if(is_array($v)) {
            $currentPath = $parent.$k;
            $paths[] = $currentPath;
            $paths = array_merge($paths, gen_path($v, $currentPath));
        } else {
            $paths[] = $parent.$v;
        }
    }

    return $paths;
}
你的方向是正确的,但有一点偏差。在你的函数中,在递归函数调用之前的return语句导致foreach循环后的所有内容都没有被调用。

0

这里有另一种解决方案,使用 RecursiveArrayIteratorRecursiveIteratorIterator

function generatePaths( array $tree ) {
  $result = array();
  $currentPath = array();

  $rii = new RecursiveIteratorIterator( new RecursiveArrayIterator( $tree ), RecursiveIteratorIterator::SELF_FIRST );
  foreach( $rii as $key => $value ) {
    if( ( $currentDepth = $rii->getDepth() ) < count( $currentPath ) ) {
      array_splice( $currentPath, $currentDepth );
    }
    $currentPath[] = is_array( $value ) ? $key : $value;
    $result[] = implode( '/', $currentPath );
  }

  return $result;
}

附注:Baconics' solution 看起来比我的快大约两倍。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接