使用PHP从另一个数组动态构建多维数组?

时间:2012-06-02 19:51:45

标签: php arrays dynamic creation

我有一个包含在数组中的数据,就像这样,

$file['info']['files'] = array(
    [0] => array(
         'length' => (int),
         'path' => array (
              [0] => 'file.txt',
         ),
    ),
    [1] => array(
         'length' => (int),
         'path' => array (
              [0] => 'directory one',
              [1] => 'file2.txt',
         ),
    ),
    [2] => array(
         'length' => (int),
         'path' => array (
              [0] => 'directory one',
              [1] => 'directory two',
              [2] => 'file3.txt',
         ),
    ),
);

$file['info']['files']数组可以包含任意数量的元素。每个path数组中包含的$file['info']['files']数组是我遇到问题的地方。

它包含有关文件结构的信息。如果只存在1个元素,那么它就是一个文件。如果存在多个元素,则从顶部开始的每个元素是下一个元素的父文件夹,最后一个元素是最后一个文件夹中的文件。以上为例,将是

的文件结构
FILE file1.txt
FOLDER directory one
     FILE file2.txt
     FOLDER directory two
          FILE {file3.txt}

我想将这些数据提取到我自己的数组结构中,如下所示,

 $sortedFiles = array(
     'file1.txt' => (int),
     'directory one' => array(
         'file2.txt' => (int),
         'directory two' => array(
              'file3.txt' => (int),
         ),
     ),
 );

到目前为止我有这个代码,

foreach($file['info']['files'] as $file) {
    // LENGTH AND PATH ARE SET
    if(isset($file['length'], $file['path'])) {
        // GET COUNT OF FILE PATH ARRAY
        $count = count($file['path']);
        // SINGLE FILE
        if($count == 1) {
            $sortedFiles[$file['path'][0]] = $file['length'];
        // FILES IN DIRECTORY
        } else {
            // BUILD ARRAY STRUCTURE FOR DIRECTORIES
        }
    }
}

我在向阵列添加目录时遇到了麻烦。我可以手动完成它,每次只检查目录的数组是否存在,如果没有创建它,如果它确实存在,那么只需要下载这么多目录然后添加到它。我使用下面的代码尝试了这个,但它只有一个目录深度(代码在上面的// BUILD ARRAY STRUCTURE所在的位置)。

// FOLDER NOT SET
if(!isset($files[$file['path'][0]])) {
    $sortedFiles[$file['path'][0]] = array($file['path'][1] => $file['length'],);
// FOLDER SET
} else {
    $sortedFiles[$file['path'][0]][$file['path'][1]] = $file['length'];
}

如何为每个存在的目录动态创建数组并添加所需的信息,同时记住目录结构可能是任何级别的深度?

感谢您抽出时间阅读我相当长的问题,感谢任何人给予我的任何帮助。

4 个答案:

答案 0 :(得分:3)

您需要递归调用函数,如下例所示:

function get_contents_dir( $dir )
{
    $names = array();

    if ( is_dir($dir) && is_readable($dir) )
    {
            foreach ( scandir($dir) as $file )
            {
                    if ( is_dir($dir."/".$file) && is_readable($dir."/".$file) )
                    {
                            $names[] = get_contents_dir($dir."/".$file);
                    }

                    if ( is_file($dir."/".$file) && is_readable($dir."/".$file) )
                    {
                            $names[] = $dir."/".$file;
                    }
            }
    }

    return $names;
}

此函数首先打开set $dir文件夹并扫描文件列表,将每个找到的文件添加到数组中,在扫描文件夹后,return ed作为函数的返回值

scandir()结果(文件夹中的文件和文件夹列表)实际上是一个文件夹时,会出现这种情况。如果发生这种情况,则递归地从它的内部调用函数(参见函数内调用函数的行$names[] = get_contents_dir($dir."/".$file);),子文件夹也将被编入索引。冲洗并重复,直到所有子文件夹都被编入索引。

如果调用该函数并让它执行,将返回一个数组。数组的每个键都是一个条目。如果它是一个文件,则链接到该键的值是该文件的名称,如果它是一个文件夹,则该值将是嵌套到前一个文件中的另一个数组。

以下是返回数组的示例转储:

array (
  0 => './libmysqlclient.so.16.0.0',
  1 => './libmysqlclient_r.so.16.0.0',
  2 => 
  array (
    0 => './libs/libboost_thread-mt.a',
    1 => './libs/libboost_thread-mt.so.1.38.0',
    2 => './libs/libmysql.dll',
    3 => './libs/libmysqlclient16_5.1.41-3ubuntu12_i386.deb',
  ),
  3 => 
  array (
    0 => './radio_sneaker/cl_auto.lua',
    1 => './radio_sneaker/sh_auto.lua',
    2 => './radio_sneaker/sh_coms.lua',
    3 => './radio_sneaker/sh_info.lua',
    4 => './radio_sneaker/sv_auto.lua',
    5 => './radio_sneaker/sv_hooks.lua',
  ),
  4 => './sv_auto.lua',
)

将此输出与在同一文件夹上运行的tree命令进行比较:

|   libmysqlclient.so.16.0.0
|   libmysqlclient_r.so.16.0.0
|   sv_auto.lua
|   
+---libs
|       libboost_thread-mt.a
|       libboost_thread-mt.so.1.38.0
|       libmysql.dll
|       libmysqlclient16_5.1.41-3ubuntu12_i386.deb
|       
\---radio_sneaker
        cl_auto.lua
        sh_auto.lua
        sh_coms.lua
        sh_info.lua
        sv_auto.lua
        sv_hooks.lua

答案 1 :(得分:1)

为什么不在php中使用join函数来合并路径以检查它是否存在?如果没有,则逐级检查文件夹是否存在,如果不存在,则创建并进一步移动。我的观点是,创建这样一个动态结构首先是困难而且容易搞砸。为什么不轻松一点?

答案 2 :(得分:1)

想象一下,你有一个表示目录结构的数组,该数组最初是空的,将逐个填充。您需要跟踪此数组中的“当前”项并迭代目录名称。在每次迭代中,如果当前项尚不存在,则在当前项下创建一个子数组,然后将当前项设置为该子数组。

这可以通过递归或迭代来完成,因为它是PHP,“当前”标记需要作为参考。

考虑到这一概述,请查看this question及其答案。输入以字符串的形式出现,但距离当前情况只有implode

答案 3 :(得分:1)

我会让你在你的代码中挣扎,但这是重要的课程。

将平面阵列转换为嵌套结构

$a = array(
    'dir1', 'dir2', 'file.txt'
);

$structure = array(array_pop($a));
foreach (array_reverse($a) as $dir) {
    $structure = array($dir => $structure);
}

print_r($structure);

将一个结构合并到另一个

$result = array_merge_recursive($result, $structure);

只需迭代所有结构进行合并。