簡體   English   中英

從 PHP 中的平面路徑數組構建目錄樹

[英]Build directory tree from flat array of paths in PHP

所以,標題可能令人困惑,但我不知道如何用這種數組結構來形容。 它肯定是一個樹結構,但至於它的創建,這就是我渴望的地方。 它似乎沒有遵循典型的遞歸數組樹構建。

我正在嘗試從一個扁平的路徑數組創建一個列目錄布局,每個路徑都在它自己的多維數組中。

該數組旨在構建 macOS Finder 列視圖樣式界面,使用FinderJS如下(來自以下數據):

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

該庫需要一個 JS 中的“item”對象數組,示例格式如下:

[{
    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

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 並傳遞給客戶端以加載:

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 ...
];

我已經嘗試創建查找數組來計算和存儲父鍵,以便在另一個構建循環期間按所需的結構級別查找,但這也不起作用。

我最初嘗試重構循環以構建基於級別的樹,但意識到必須遞歸才能首先構建子數組或逐級查看該項目在生成之前是否已經存在等級。

表面上看起來相當簡單,因為您正在每個級別構建一個數組,但是檢查“目錄”是否存在於該級別,如果存在,則輸入它,然后檢查該級別是否存在下一個級別項目,如果沒有則創建,然后輸入該數組。 我假設以遞歸方式執行最后一部分,根據每條路徑的需要沿鏈向下進行多次。

但在這一點上,我嘗試過的所有途徑都已經筋疲力盡,而且我有點被這個腦筋急轉彎所困。 任何幫助將不勝感激!

到目前為止,我所擁有的最好的是我制作的這個小樹生成器,但僅限於每個分支。 我需要另一個循環,我假設將級別 1 的所有鍵合並在一起,與 2、3 等相同......

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 ...
)

這是如此接近,但由於明顯的原因並不完全存在,如果父級已經存在,它不會向下遍歷到目錄中。 它是否遵循典型的樹木建築? 感覺有,但是看不出來。。。

您可以分兩步執行此操作:

  • 創建關聯數組的層次結構,其中標簽是鍵,嵌套數組對應於子項。
  • 將該結構轉換為目標結構

代碼:

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))條件,並簡化為以下版本:

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);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM