如何在PHP中将一个简单的文件路径数组转换为表示文件层次结构的嵌套数组



我需要用PHP编写一个函数,该函数接受以下输入数组:

$inputArray = [
[
"path" => "/C",
"basename" => "C",
"size" => 4096,
"modified" => 1540579748,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/Recycle.Bin",
"basename" => "Recycle.Bin",
"size" => 0,
"modified" => 1539012172,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/Pictures",
"basename" => "Pictures",
"size" => 3164422144,
"modified" => 1540581569,
"type" => "file",
"contents" => []
],
[
"path" => "/C/Videos",
"basename" => "Videos",
"size" => 970752,
"modified" => 1540579792,
"type" => "file",
"contents" => []
],
[
"path" => "/C/Documents and Settings",
"basename" => "Documents and Settings",
"size" => 4096,
"modified" => 1539022708,
"type" => "link",
"contents" => []
],
[
"path" => "/C/Documents and Settings/Public",
"basename" => "Public",
"size" => 4096,
"modified" => 1539012079,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/Documents and Settings/desktop.ini",
"basename" => "desktop.ini",
"size" => 174,
"modified" => 1506692592,
"type" => "file",
"contents" => []
],
[
"path" => "/C/PerfLogs",
"basename" => "PerfLogs",
"size" => 0,
"modified" => 1506692704,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/Program Files",
"basename" => "Program Files",
"size" => 4096,
"modified" => 1540579745,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/Program Files (x86)",
"basename" => "Program Files (x86)",
"size" => 4096,
"modified" => 1506692707,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/ProgramData",
"basename" => "ProgramData",
"size" => 4096,
"modified" => 1539012665,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/Recovery",
"basename" => "Recovery",
"size" => 0,
"modified" => 1539022717,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/System Volume Information",
"basename" => "System Volume Information",
"size" => 4096,
"modified" => 1539012967,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/Users",
"basename" => "Users",
"size" => 4096,
"modified" => 1539012384,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/Windows",
"basename" => "Windows",
"size" => 24576,
"modified" => 1539011957,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/pagefile.sys",
"basename" => "pagefile.sys",
"size" => 1207959552,
"modified" => 1540581479,
"type" => "file",
"contents" => []
],
[
"path" => "/C/swapfile.sys",
"basename" => "swapfile.sys",
"size" => 268435456,
"modified" => 1540581479,
"type" => "file",
"contents" => []
]
];

并产生以下输出阵列:

$outputArray = [
[
"path" => "/C",
"basename" => "C",
"size" => 4096,
"modified" => 1540579748,
"type" => "dir",
"contents" => [
[
"path" => "/C/Recycle.Bin",
"basename" => "Recycle.Bin",
"size" => 0,
"modified" => 1539012172,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/Pictures",
"basename" => "Pictures",
"size" => 3164422144,
"modified" => 1540581569,
"type" => "file",
"contents" => []
],
[
"path" => "/C/Videos",
"basename" => "Videos",
"size" => 970752,
"modified" => 1540579792,
"type" => "file",
"contents" => []
],
[
"path" => "/C/Documents and Settings",
"basename" => "Documents and Settings",
"size" => 4096,
"modified" => 1539022708,
"type" => "link",
"contents" => [
[
"path" => "/C/Documents and Settings/Public",
"basename" => "Public",
"size" => 4096,
"modified" => 1539012079,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/Documents and Settings/desktop.ini",
"basename" => "desktop.ini",
"size" => 174,
"modified" => 1506692592,
"type" => "file",
"contents" => []
]
]
],
[
"path" => "/C/PerfLogs",
"basename" => "PerfLogs",
"size" => 0,
"modified" => 1506692704,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/Program Files",
"basename" => "Program Files",
"size" => 4096,
"modified" => 1540579745,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/Program Files (x86)",
"basename" => "Program Files (x86)",
"size" => 4096,
"modified" => 1506692707,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/ProgramData",
"basename" => "ProgramData",
"size" => 4096,
"modified" => 1539012665,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/Recovery",
"basename" => "Recovery",
"size" => 0,
"modified" => 1539022717,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/System Volume Information",
"basename" => "System Volume Information",
"size" => 4096,
"modified" => 1539012967,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/Users",
"basename" => "Users",
"size" => 4096,
"modified" => 1539012384,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/Windows",
"basename" => "Windows",
"size" => 24576,
"modified" => 1539011957,
"type" => "dir",
"contents" => []
],
[
"path" => "/C/pagefile.sys",
"basename" => "pagefile.sys",
"size" => 1207959552,
"modified" => 1540581479,
"type" => "file",
"contents" => []
],
[
"path" => "/C/swapfile.sys",
"basename" => "swapfile.sys",
"size" => 268435456,
"modified" => 1540581479,
"type" => "file",
"contents" => []
]
]
]
];

我知道这可以用递归来完成,但我很难做到。如果有人能给我指明正确的方向或提供一个有效的解决方案,那将非常酷。

如果数组尚未排序,则按path排序:

usort($inputArray, function ($a, $b) {
return $a['path'] <=> $b['path'];
});

然后通过path:递归嵌套项目

function nest(&$directory)
{
for ($i = 0; $i < count($directory); $i++)
{
while ($i + 1 < count($directory) && strpos($directory[$i + 1]['path'], $directory[$i]['path'] . '/') === 0)
{
$directory[$i]['contents'][] = $directory[$i + 1];
array_splice($directory, $i + 1, 1);
}
nest($directory[$i]['contents']);
}
}

在不区分大小写的文件系统(如Windows)上,您可能希望用stripos()替换strpos(),但我没有对此进行测试,所以由您决定。

如果您能够使用对象数组,您可以利用对象像引用一样传递的方式来简化创建这种结构。

sort($inputArray);
foreach ($inputArray as $item) {
$item = (object) $item;
$files[$item->path] = $item;
$files[substr($item->path, 0, strrpos($item->path, '/'))]->contents[] = $item;
}
$result = reset($files);

如果对象不适合您,JSON编码/解码可以将结果中的对象转换为数组。

$result = json_decode(json_encode($result), true);

最新更新