从PHP中的平面路径构建目录树 [英] Build directory tree from flat array of paths in PHP

查看:82
本文介绍了从PHP中的平面路径构建目录树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,标题可能令人困惑,但是我不确定如何用这种数组结构写词.当然,这是一个树形结构,但是对于它的创建,这就是我渴望的地方.它似乎没有遵循原型递归数组树的构建.

So, the title maybe confusing but I'm not sure how to word this kind of array structure. It's a tree structure for sure, but as to its creation, that's where I'm hankering. It doesn't appear to follow prototypical recursive array tree building.

我正在尝试从平面路径数组创建列目录布局,每个路径都在其自己的多维数组内.

I'm trying to create a column directory layout from a flat array of paths, each path being inside its own multi dimensional array.

此数组旨在使用 FinderJS 来构建macOS Finder列视图样式界面,如下所示(来自下面的数据):

This array is designed to build a macOS Finder column view style interface, using FinderJS like follows (from the data below):

| elections   > | id                    |           |            |
|               | name                  |           |            |
|               | description         > | field     |            |
|               | dynamic_parent_id   > | field     |            |
|               | method              > | field   > | field_more |

该库需要使用JS格式的"item"对象数组,格式如下:

The library requires an array of 'item' objects, in JS, in the following example format:

[{
    label: 'elections',
    children: [{
        label: 'id'
    }, {
        label: 'name'
    }, {
        label: 'description',
        children: [{
            label: 'field'
        }]
    }, {
        label: 'dynamic_parent_id',
        children: [{
            label: 'field'
        }]
    }, {
        label: 'method',
        children: [{
            label: 'field',
            children: [{
                label: 'field_more'
            }]
        }]
    }]
}]

我正在尝试从以下PHP数组中获取以上内容,该数组名为 $ fields :

I'm trying to get the above from the following PHP array, this array named $fields:

Array
(
    [0] => Array
        (
            [0] => elections
            [1] => id
        )

    [1] => Array
        (
            [0] => elections
            [1] => name
        )

    [2] => Array
        (
            [0] => elections
            [1] => description
            [2] => field
        )

    [3] => Array
        (
            [0] => elections
            [1] => dynamic_parent_id
            [2] => field
        )

    [4] => Array
        (
            [0] => elections
            [1] => method
            [2] => field
            [3] => field_more
        )

...[and so forth]...
];

需要重新构建为以下结构,以允许进行json_encode并传递给客户端进行加载:

which needs to be reformed into the following structure, allowing a json_encode to take place and passed to the client to load:

Array
(
    [0] => Array
        (
            [label] => elections
            [children] => Array
                (
                    [0] => Array
                        (
                            [label] => id
                            [children] => Array
                                (
                                )
                        )
                    [1] => Array
                        (
                            [label] => name
                            [children] => Array
                                (
                                )
                        )
                    [2] => Array
                        (
                            [label] => description
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [label] => field
                                            [children] => Array
                                                (
                                                )
                                        )
                                )
                        )
                    [3] => Array
                        (
                            [label] => dynamic_parent_id
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [label] => field
                                            [children] => Array
                                                (
                                                )
                                        )
                                )
                        )
                    [4] => Array
                        (
                            [label] => method
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [label] => field
                                            [children] => Array
                                                (
                                                    [0] => Array
                                                        (
                                                            [label] => field_more
                                                            [children] => Array
                                                                (
                                                                )
                                                        )
                                                )
                                        )
                                )
                        )
                )
        )
)
... and so forth ...
];

我尝试根据所需的结构级别创建查找数组,以在另一个构建循环中计算并存储要查找的父键,但这都不起作用.

I've tried creating lookup arrays to calculate and store parent keys to lookup during another build loop by the required structure level, but that isn't working either.

我尝试重新构造循环以最初基于级别构建树,但意识到必须先递归才能首先构建子数组或按级别查看该项目之前是否已经存在在上述级别上生成.

I've tried to re-factor the loops to build a tree based on level initially, but realised that would have to be recursive in order to build the child arrays first or go by level to see if the item already exists before generation on said level.

从表面上看,这很简单,因为您正在每个级别构造一个数组,但是检查目录"是否在该级别还存在,如果存在,请输入它,然后检查下一个级别项是否存在该级别,如果没有创建该级别,然后输入该数组.我假设递归地执行最后一部分,按照每个路径的要求沿着链条向下走了多次.

It seems on the surface fairly simple, as you are constructing an array at each level, but checking if the 'directory' exists yet at that level, if it does, enter it and then check that the next level item exists at that level, creating if it doesn't and then entering that array. Performing the last part recursively, I assume, going down the chain as many times as required for each path.

但是,在这一点上,我尝试过的所有方法都已经筋疲力尽了,我对这个大脑筋急转弯有些卡住了.任何帮助将不胜感激!

But at this point, all avenues I've tried I've exhausted and I'm a little stuck on this brain teaser. Any help would be greatly appreciated!

到目前为止,我所能获得的最好的就是我制作的这个小树生成器,但仅针对每个分支.我需要另一个循环,我假设将级别1的所有键合并到一起,与2、3等相同.

The best I've got so far is this little tree builder I've made, but only for each branch. I'd need another loop I assume to take all the keys at level 1 and merge them together, same with 2, 3, etc...

function buildTree(array $branches): array
{
    if (count($branches)) {
        $branches = array_values($branches);
        $newBranch = $branches[0];
        unset($branches[0]);

        return [
            'label' => $newBranch,
            'children' => $this->buildTree($branches)
        ];
    } else {
        return [];
    }
}

foreach ($fields as $field) {
    $treePieces[] = $this->buildTree($field);
}

print_r($treePieces);

给出以下输出:

Array
(
    [0] => Array
        (
            [label] => elections
            [children] => Array
                (
                    [label] => id
                    [children] => Array
                        (
                        )
                )
        )
    [1] => Array
        (
            [label] => elections
            [children] => Array
                (
                    [label] => name
                    [children] => Array
                        (
                        )
                )
        )
    [2] => Array
        (
            [label] => elections
            [children] => Array
                (
                    [label] => description
                    [children] => Array
                        (
                        )
                )
        )
... and so forth ...
)

如此接近,但由于明显的原因并没有那么接近,如果父级已经存在,它就不会遍历到目录中.它遵循典型的树形建筑吗?我觉得可以,但是我看不到...

Which is so close, but not quite there for obvious reasons, it's not traversing down into the directory if the parent already exists. Does it follow typical tree building? I feel it does, but I can't quite see it...

推荐答案

您可以分两个步骤进行操作:

You could do this in two steps:

  • 创建一个关联数组的层次结构,其中标签为键,而嵌套数组对应于子级.
  • 将该结构转换为目标结构

代码:

function buildTree($branches) {
    // Create a hierchy where keys are the labels
    $rootChildren = [];
    foreach($branches as $branch) {
        $children =& $rootChildren;
        foreach($branch as $label) {
            if (!isset($children[$label])) $children[$label] = [];
            $children =& $children[$label];
        }
    }
    // Create target structure from that hierarchy
    function recur($children) {
        $result = [];
        foreach($children as $label => $grandchildren) {
            $node = ["label" => $label];
            if (count($grandchildren)) $node["children"] = recur($grandchildren);
            $result[] = $node;
        }
        return $result;
    }
    return recur($rootChildren);
}

这样称呼它:

$tree = buildTree($branches);

上面没有任何子代时,将省略 children 键.如果在这种情况下也需要 children 键,则只需删除 if(count($ grandchildren))条件,并简化为以下版本:

The above will omit the children key when there are no children. If you need to have a children key in those cases as well, then just remove the if (count($grandchildren)) condition, and simplify to the following version:

function buildTree($branches) {
    // Create a hierchy where keys are the labels
    $rootChildren = [];
    foreach($branches as $branch) {
        $children =& $rootChildren;
        foreach($branch as $label) {
            if (!isset($children[$label])) $children[$label] = [];
            $children =& $children[$label];
        }
    }
    // Create target structure from that hierarchy
    function recur($children) {
        $result = [];
        foreach($children as $label => $grandchildren) {
            $result[] = ["label" => $label, "children" => recur($grandchildren)];
        }
        return $result;
    }
    return recur($rootChildren);
}

这篇关于从PHP中的平面路径构建目录树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆