我很难弄清楚如何递归迭代数组并创建一个数组的“路径”
我有两个数组。一个是目录树的数组,看起来像这样:
$directoryTree = [
'accounting' => [
'documents' => [
],
'losses' => [
],
'profit' => [
]
],
'legal' => [
'documents' => [
]
]
];
另一个是文件列表,用于指定文件应驻留在哪个目录“path”:
$fileList = [
[
'name' => 'Overview.doc',
'dir_path' => []
],
[
'name' => 'Incorporation.doc',
'dir_path' => []
],
[
'name' => 'Profit And Loss.xls',
'dir_path' => ['accounting']
],
[
'name' => 'Profit 1.xls',
'dir_path' => ['accounting', 'profit']
],
[
'name' => 'Loss 1.xls',
'dir_path' => ['accounting', 'losses']
],
[
'name' => 'TOS Draft.doc',
'dir_path' => ['legal', 'documents']
]
[
'name' => 'Accounting Doc.pdf',
'dir_path' => ['accounting', 'documents']
],
];
基本上我要做的是遍历$directoryTree
并查看$fileList
中是否有任何元素,其中包含迭代器所在的“路径”。如果有元素应该添加在那里。
最终数组应该类似于this:
$finalOutput = [
'accounting' => [
'documents' => [
'Accounting Doc.pdf'
],
'losses' => [
'Loss 1.xls'
],
'profit' => [
'Profit 1.xls'
],
'Profit And Loss.xls'
],
'legal' => [
'documents' => [
'TOS Draft.Doc'
]
],
'Overview.doc',
'Incorporation.doc',
];
我所做的尝试并没有让我走得太远。我一直试图以递归方式遍历数组而陷入困境,并且不确定如何解决下一个问题。
答案 0 :(得分:1)
以下代码应该可以解决问题。考虑一下伪代码。它真的是javascript,java和单词的组合哈哈。
@stck是一个字符串数组,跟踪路径
//function should return an empty $fileList signaling all files have been processed
function treeTraversal($directoryTree, $fileList, stck) {
//begins by processing all the files that are children of the root directory
//e.g. those with dir_name =[]
//removes them from $fileList so we don't have to keep iterating over them
if(stck.length == 0) {// == 0 only once, when processing first child of root
for(var i = 0; i < $fileList.length; i ++) {
if($fileList[i].dir_name.length == 0) {
$directoryTree.push($fileList[i]);
$fileList.removeElementAtIndex(i)
}
}
}
// now recursively traverse the tree. Record the path in var called stck
for(var i = 0; i < $directoryTree.length; i++) {
stck.push($directoryTree[i]); // $directoryTree[i] refers to name of directory not its contents
if($directoryTree[i] is array)
$fileList = treeTraversal($directoryTree[i], $fileList, stck);
for(var j = 0; j < $fileList.length; j++) {
if($fileList[j].dir_path == stck) {
$directoryTree.push($fileList[j]);
$fileList.removeElementAtIndex(j);
}
}
stck.pop();
return $fileList
}
答案 1 :(得分:1)
更难以迭代$fileList
并将它们放在正确的目录数组下吗? e.g。
$finalOutput = $directoryTree;
foreach ($fileList as $file) {
$current_dir &= $finalOutput;
foreach ($file['dir_path'] as $dir) {
if (isset($current_dir[$dir])) {
$current_dir &= $current_dir[$dir];
} else {
$current_dir = null;
break;
}
}
if (is_array($current_dir)) {
$current_dir[] = $file['name'];
} else {
// do you want to do anything if dir is not there?
}
}
注意:我没有运行代码,但应该知道它是如何工作的。
如果由于某些未说明的原因,您必须反复遍历$directoryTree
,那么您应该小心确保逻辑在O(n)
(或其附近)而不是O(n^2)
时间运行。一个简单的算法如下:
$fileList
并生成所有目录的地图 - &gt;文件$directoryTree
并填写地图中的文件答案 2 :(得分:0)
有趣的问题。我的答案实际上没有按照&#34;怎么做&#34;来回答这个问题,但它表明,一旦可以更容易地解决复杂问题,你需要把它复杂化,可能这些小解决方案可以在以后重复使用。
基本上,您需要能够设置&#34;嵌套键&#34;的值。我遇到了questions(并亲自面对)关于获取&#34;嵌套键&#34;的值。
所以我决定实现隐藏递归的数组访问类,并帮助使用类似数组的键来获取嵌套值。您可以查看repo。对代码的解释实际上符合问题的范畴,但由于时间很长,我无法在此解释。重点是数组访问方法隐藏了递归。
鉴于此课程,您的问题可以简化为$directoryTree = new CompositeKeyArray($directoryTree);
foreach ($fileList as $file) {
if (
!empty($file['dir_path'])
&& !isset($directoryTree[$file['dir_path']])
) {
throw new Exception;
}
array_push($file['dir_path'], []);
$directoryTree[$file['dir_path']] = $file['name'];
}
var_dump($directoryTree->toArray());
上的简单循环:
add
在其中一条评论中,您提到过您希望在不存在的路径上抛出异常。 if部分处理这个。
这是working demo。