【问题标题】:How to turn this PHP array structure into multi-dimensional tree?如何将这个 PHP 数组结构变成多维树?
【发布时间】:2012-10-14 06:33:22
【问题描述】:

我有一个二维 PHP 数组,我需要将其转换为一棵树。每个内部数组中的“路径”值是当前节点的枚举路径。 (我从 Bill Karwin 关于 SQL 反模式的书中得到这个想法)。

所以,我开始使用的数组看起来像这样:

array(
[1] => array('name' => 'Animals', 'path' => '1/'),
[2] => array('name' => 'Birds', 'path' => '1/3/'),
[3] => array('name' => 'Cockatoos', 'path' => '1/3/5/'),
[4] => array('name' => 'Fish', 'path' => '1/2/'),
[5] => array('name' => 'Kookaburras', 'path' => '1/3/4/')
)

您可能已经收集到,外部数组的索引是没有意义的。我只是在“名称”上按字母顺序对内部数组进行了排序,PHP 在外部数组上分配了数字索引。

就'path'值而言,每条路径的最后一段是节点的伪ID,即Animals是节点1,Birds是节点3。您可以看到完整路径描述了路线到给定的节点,例如'Cockatoos' 的父级是 'Birds',后者的父级是 'Animals'。

我想保持节点的字母顺序,但按其父级分组。换句话说,我想要一个看起来像这样的数组(按其自然顺序):

[1]         => 'Animals'
[1][3]      => 'Birds'
[1][3][5]   => 'Cockatoos'
[1][3][4]   => 'Kookaburras'
[1][2]      => 'Fish'

我计划递归地迭代这个以打印树的可视化表示。

在尝试从一种类型的数组转换为另一种类型时,我的方法使用了递归、变量变量和正则表达式,但我一直遇到障碍。

另外,是否有我应该考虑的 SPL 数据结构或迭代器?

非常感谢!

编辑:对不起,应该提到树的深度是可变的。上面的例子有三个层次,但实际上会有更多。

【问题讨论】:

    标签: php arrays data-structures recursive-datastructures


    【解决方案1】:

    由于使用了 Eval() 函数(代表评估),这将起作用,无论树的深度如何。但是字母表的排序还不能正常工作。因为父数组的索引保持不变,所以会混淆。但是至少你已经可以建造一棵树了:)

    <?php
    $a = array(
            array('name' => 'Animals', 'path' => '1/'), 
            array('name' => 'Birds', 'path' => '1/3/'), 
            array('name' => 'Eagles', 'path' => '1/3/3/'),
            array('name' => 'Cockatoos', 'path' => '1/3/5/'), 
            array('name' => 'Fish', 'path' => '1/2/'), 
            array('name' => 'Kookaburras', 'path' => '1/3/4/')
        );
    Iterate($a);
    $tree = Iterate($a);
    
    var_dump($tree);
    
    OneLevelDeeper($tree);
    var_dump($tree);
    
    function Iterate($ChildArray)
    {
        $TreeArray;
        foreach($ChildArray as $Key => $Value)
        {
            //echo $Key.': '.$Value['name']."\r\n";
            $exp = explode('/', $Value['path']);
            $path;
            foreach($exp as $int)
            {
                if($int != "")
                {
                    $path[] = $int;
                }
            }
    
            //Using Eval() function of PHP
            $BuildSourceToEvaluate = '$TreeArray';
            for($i=0; $i<(count($path)-1); $i++)
            {
                $BuildSourceToEvaluate .= '[$path['.$i.']]';
            }
            $BuildSourceToEvaluate .= '[] = $Value[\'name\'];';
            echo $BuildSourceToEvaluate."\r\n";
            Eval($BuildSourceToEvaluate);
            //print_r($path);
            /*
            switch(count($path))
            {
                case 0:
                break;
                case 1:
                    $TreeArray[] = $Value['name']; 
                    //$TreeArray[$path[0]] = $Value['name']; //Use this for unique paths and keeping hold of the last ID in the tree path
                    //$TreeArray[$path[0]][] = $Value['name']; //Use this for non-unique tree paths
                break;
                case 2:
                    $TreeArray[$path[0]][] = $Value['name']; 
                    //$TreeArray[$path[0]][$path[1]] = $Value['name']; //Use this for unique paths and keeping hold of the last ID in the tree path
                    //$TreeArray[$path[0]][$path[1]][] = $Value['name']; //Use this for non-unique tree paths
                break;
                case 3:
                    $TreeArray[$path[0]][$path[1]][] = $Value['name'];
                    //$TreeArray[$path[0]][$path[1]][$path[2]] = $Value['name']; //Use this for unique paths and keeping hold of the last ID in the tree path
                    //$TreeArray[$path[0]][$path[1]][$path[2]][] = $Value['name']; //Use this for non-unique tree paths
                break;
            }
            */
            unset($path);
        }
        return $TreeArray;
    }
    
    
    function OneLevelDeeper(&$a)
    {
        sort($a);
        foreach($a as $Key => $Value)
        {
            if(is_array($Value))
            {
                sort($a[$Key]);
                OneLevelDeeper($a[$Key]);
            }
        }
    }
    
    ?>
    

    【讨论】:

    • 迈克,谢谢你给这个破解。不过,请参阅我原来的问题中的编辑。树的深度是可变的。对不起,我应该在一开始就说明这一点。有兴趣看看您现在如何解决问题...
    • @Kim - 这仍然没有问题。树的最大深度可能是?您可以将新案例添加到案例切换,以增加树的深度。否则你将不得不使用 PHP 的 Eval() 函数。
    猜你喜欢
    • 1970-01-01
    • 2021-12-28
    • 2012-12-10
    • 2018-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多