列表到树结构

时间:2017-05-31 10:42:33

标签: php

我有以下示例数组列表;

$relationships = ['contact', 'property', 'contact.type1', 'contact.type2', 'contact.type1.color1', 'contact.type1.color2'];

我想要一个像这样的结构;

[
    contact => [ 
                 type1 => [
                             color1 => [], 
                             color2 => []
                          ], 
                 type2 => [] 
               ], 
    property => []
]

我创建了以下代码;

start();

function start()
{
    $myTree = array();

    $relations = ['contact', 'property', 'contact.type1', 'contact.type2', 'contact.type1.color1', 'contact.type1.color2'];

    foreach ($relations as $relation) {

        $myTree = getRelationTree($relation, $myTree);
    }

    var_dump($myTree);
}

function getRelationTree($name, $tree)
{
    $sections = explode('.', $name);

    $main = array_shift($sections);

    if (!array_search($main, $tree)) {
        $tree[$main] = [] ;
    }

    // Has nested relationships
    if (count($sections) > 0) {
        $children  = [];
        $children[] = getRelationTree(join('.',$sections), $children);

        $tree[$main] = $children;
    }

    return $tree;
}

但是,根据上述预期结果,我得到的结果缺少color1

你能告诉我我的代码有什么问题吗?我如何修复它以给我想要的结果?感谢

2 个答案:

答案 0 :(得分:2)

我刚刚使用引用而不是recurency编写了更简单的代码。

查看我的代码,它包含评论说明发生了什么:

<?php

$relationships = ['contact', 'property', 'contact.type1', 'contact.type2', 'contact.type1.color1', 'contact.type1.color2'];

$tree = []; 
foreach($relationships as $path) {
    $parts = explode('.', $path);

    //represents current position in current $path
    $currentNode = &$tree;

    foreach($parts as $part) {
        //if this part doesn't exist yet, let's create it
        if(empty($currentNode[$part])) {
            $currentNode[$part] = [];
        }
        //move forward in out $path position
        $currentNode = &$currentNode[$part];
    }
    //after we finish a particular path, we reset the position.
    unset($currentNode);
}

工作示例:https://3v4l.org/o3MGP

编辑:这是对你错误的解释:

在我分析了您的代码后,我可以在您的函数getRelationTree()中看到您的错误:

// Has nested relationships
if (count($sections) > 0) {
    $children  = []; 
    $children[] = getRelationTree(implode('.',$sections), $children);

    $tree[$main] = $children; // <==this line exactly
}

您正在覆盖现有的值。

因此,当您的树已经解析了'contact.type1.color1'路径并且您正在解析'contact.type1.color2'时,您将覆盖$tree['contact']已经具有'type1.color1'值且新子树的type1.color2 #!/usr/bin/perl use Modern::Perl; use Mojolicious::Lite; use extmod; sub hello { say "hello"; } get "/" => sub { my $c = shift; extmod::put(); $c->render(text=>"ok"); }; app->start; 。等等。

答案 1 :(得分:0)

这是另一个答案的替代方案,使用递归(准备好复制粘贴):

$relationships = ['contact', 'property', 'contact.type1', 'contact.type2', 'contact.type1.color1', 'contact.type1.color2'];

$arr = array();

foreach($relationships as $value){
    add($arr, $value);
}

function add(&$arr, $value){
    if(strpos($value, '.') !== false){ // if there are sublevels
        $tmp = explode('.', $value, 2); // separate first from rest of levels
        $item = $tmp[0]; // get what's before first dot
        $children = $tmp[1]; // get what's after the first dot
        if(empty($arr[$item])){ // if not yet created, create item
            $arr[$item] = array();
        }
        add($arr[$item], $children); // add the item's child / children
        return; // prevent from overriding
    }
    $arr[$value] = array();
}

echo '<pre>';
print_r($arr);