PHP多维关联数组转换(URL文件夹结构为分层数组)

时间:2017-04-19 17:16:31

标签: php arrays recursion tree

我扭曲了我的大脑,试图将多维关联数组转换为多维非关联数组,并且到了我决定寻求帮助的地步......

整个故事:

甲。我有一组URL及其KPI(具有任意文件夹深度):

网址,访问次数

  1. www.example.com
  2. www.example.com/resource1,100
  3. www.example.com/folderA/resource2,200
  4. www.example.com/folderA/resource3,300
  5. www.example.com/folderB/resource4,400
  6. B中。在StackOverflow的帮助下(令人惊讶的是几行PHP - >参见here)我能够将其转换为分层数组,将URL结构表示为文件夹:

    Array
    (
    [www.example.com] => Array
        (
            [folderA] => Array
                (
                    [resource2] => Array
                        (
                            [visits] => 200
                        )
    
                    [resource3] => Array
                        (
                            [visits] => 300
                        )
    
                )
    
            [folderB] => Array
                (
                    [resource4] => Array
                        (
                            [visits] => 400
                        )
    
                )
    
            [resource1] => Array
                (
                    [visits] => 100
                )
    
        )
    
     )
    

    ℃。但是,现在,我需要将这个数组放入以下结构中(子项必须是非关联数组),这对我来说是一个真正的大脑扭曲......

    Array
    (
    [name] => www.example.com
    [isFolder] => 1
    [children] => Array
        (
            [0] => Array
                (
                    [name] => folderA
                    [isFolder] => 1
                    [children] => Array
                        (
                            [0] => Array
                                (
                                    [name] => resource2
                                    [isFolder] => 0
                                    [kpis] => Array
                                        (
                                            [visits] => 200
                                        )
    
                                    [children] => Array
                                        (
                                        )
    
                                )
    
                            [1] => Array
                                (
                                    [name] => resource3
                                    [isFolder] => 0
                                    [kpis] => Array
                                        (
                                            [visits] => 300
                                        )
    
                                    [children] => Array
                                        (
                                        )
    
                                )
    
                        )
    
                )
    
            [1] => Array
                (
                    [name] => folderB
                    [isFolder] => 1
                    [children] => Array
                        (
                            [0] => Array
                                (
                                    [name] => resource4
                                    [isFolder] => 0
                                    [kpis] => Array
                                        (
                                            [visits] => 400
                                        )
    
                                    [children] => Array
                                        (
                                        )
    
                                )
    
                        )
    
                )
    
            [2] => Array
                (
                    [name] => resource1
                    [isFolder] => 0
                    [kpis] => Array
                        (
                            [visits] => 100
                        )
    
                    [children] => Array
                        (
                        )
    
                )
    
        )
    
    )
    

    任何人都可以帮助解决如何实现这一目标的方法吗?通过从步骤B转换数组或从头开始使用步骤A中的原始URL ... 任何帮助非常赞赏! 非常感谢!

1 个答案:

答案 0 :(得分:0)

下面是一个可以满足你想要的功能。它使用在树中移动的引用,并在必要时将数据添加到该引用引用的数组中。

我希望这些评论能够充分解释代码的作用。

$sourceArray = [
    'www.example.com' => 0,
    'www.example.com/resource1' => 100,
    'www.example.com/folderA/resource2' => 200,
    'www.example.com/folderA/resource3' => 300,
    'www.example.com/folderB/resource4' => 400,
];

function convertToStructure($sourceArray)
{
    // Initialize the tree
    $tree = [
        'name' => 'root',
        'isFolder' => 1,
        'children' => [],
    ];

    // Do nothing if sourceArray is not an array
    if(!is_array($sourceArray)){
        return $tree;
    }

    // Loop through the source array
    foreach($sourceArray as $path => $visits){
        // Get a reference to the target tree
        $treeReference = &$tree;

        // Split the path into pieces
        $path = explode('/', $path);

        // For each piece:
        foreach($path as $key => $name){
            // Get the childKey if the child already exists
            $childKey = findChild($treeReference, $name);

            // Create a new child otherwise
            if ($childKey === false) {
                $treeReference['children'][] = [
                    'name' => $name,
                    'isFolder' => 0,
                    'children' => [],
                ];

                // Get the key of the new child item
                end($treeReference['children']);
                $childKey = key($treeReference['children']);
            }

            // Change the reference to the correct child item.
            $treeReference = &$treeReference['children'][$childKey];

            // Set isFolder if necessary
            $isFolder = ($key == count($path) - 1 ? 0 : 1);
            if(!empty($isFolder)){
                $treeReference['isFolder'] = $isFolder;
            }

            // Set visits if necessary
            if(!empty($visits)){
                $treeReference['isFolder'] = ['kpis' => ['visits' => $visits]];
            }
        }
    }

    return $tree;
}

function findChild($tree, $name)
{
    if(empty($tree['children'])){
        return false;
    }

    foreach($tree['children'] as $key => $child){
        if($child['name'] == $name){
            return $key;
        }
    }
    return false;
}

$treeStructure = convertToStructure($sourceArray);