Php:将平面数组转换为树状结构

Php:将平面数组转换为树状结构,php,xml,arrays,sorting,Php,Xml,Arrays,Sorting,我需要有关数组转换的帮助。我有一个平面阵列,如下所示: Array ( [0] => av_one_third [1] => av_icon_box [2] => /av_icon_box [3] => av_button [4] => av_icon_box [5] => /av_icon_box [6] => /av_one_third ) 这个数组的值实际上是来自类似xml结构的标记。我现在需要的是将此数组转换为类似以下结构的嵌套

我需要有关数组转换的帮助。我有一个平面阵列,如下所示:

Array
(
[0] =>  av_one_third
[1] =>  av_icon_box
[2] =>  /av_icon_box
[3] =>  av_button
[4] =>  av_icon_box
[5] =>  /av_icon_box
[6] =>  /av_one_third

)
这个数组的值实际上是来自类似xml结构的标记。我现在需要的是将此数组转换为类似以下结构的嵌套数组:

[0] => Array
    (
        [tag] => av_one_third
        [content] => Array
            (
                [1] => Array
                    (
                        [tag] => av_icon_box
                        [content] => Array
                            (
                            )

                    )

                [2] => Array
                    (
                        [tag] => av_button
                        [content] => Array
                            (
                            )

                    )  

                [3] => Array
                    (
                        [tag] => av_icon_box
                        [content] => Array
                            (
                            )

                    )


            )

    )
etc
有没有一个简单的方法可以做到这一点?我的第一个想法是将数组转换为xml字符串,并使用phps原生xml函数之一,但问题是自动关闭标记没有这样标记。在上面的例子中,av_按钮标记没有我尝试过的xml解析函数的结束标记抛出

一些额外要求: -元素可以容纳任意数量的子元素 -最终数组必须保持正确的顺序

是否有任何智能阵列排序功能可以轻松解决此问题? 如果有任何提示,我们将不胜感激


致以最良好的祝愿:)

您的数组具有典型的平面结构,编码层次结构。但前提是你修复了其中的错误

它的工作原理与下面的PHP代码类似,包括异常,告诉数据中的错误在哪里,以便您可以修复数据(您可以在此网站上找到类似的示例,例如,请参阅中的链接问题):

  • 初始化树数组中的根条目。您可以在其中添加子项

    $tree     = ['children' => []];
    
  • 创建指向树的指针数组,其第一个元素(级别0)指向树的根元素:

    $pointers = [&$tree];
    
  • 现在检查数据中的每一行:

    foreach ($data as $index => $line) {
    
  • 决定是否关闭该行并存储决策结果:

    $close = '/' === $line[0];
    
  • 存储指针的当前计数:

    $count = count($pointers);
    
  • 如果行未关闭,请打开新元素并继续:

    $pointers[$count]                   = ['tag' => $line, 'children' => []];
    $pointers[$count - 1]['children'][] = & $pointers[$count];
    continue;
    
  • 如果该行确实关闭,请验证标记名是否匹配,如果匹配,请删除上次创建的指针:

    if ($count === 1) {
        throw new RuntimeException('Can not close on lowest level.');
    }
    
    $name = $pointers[$count - 1]['tag'];
    
    if ($name !== substr($line, 1)) {
        throw new RuntimeException(
            "Invalid closing element <$line> (line #$index) in <$name>"
        );
    }
    
    array_pop($pointers);
    
  • 结果是可以在根节点的第一个子节点中找到的数组。可以将其分配给变量,然后删除不需要的引用:

    $result = &$tree['children'][0];
    unset($tree);
    print_r($result);
    
  • 如果数据正确,它将输出:

    Array
    (
        [tag] => av_one_third
        [children] => Array
            (
                [0] => Array
                    (
                        [tag] => av_icon_box
                        [children] => Array
                            (
                            )
                    )
                [1] => Array
                    (
                        [tag] => av_button
                        [children] => Array
                            (
                            )
                    )
                [2] => Array
                    (
                        [tag] => av_icon_box
                        [children] => Array
                            (
                            )
                    )
            )
    )
    

    你确定你不需要使用一个?否则您需要创建一个递归函数。谢谢!我不知道为什么会关闭,但这正是我想要的:)它很可能关闭了,因为目前还不清楚你做了什么。更好地展示你的尝试和你遇到的障碍,这样问题就更清楚了。顺便说一句:XML解决方案更简单,但它不提供数组。谢谢!实际上,我已经完成了xml解决方案,但由于带有标记的初始数组是由用户输入生成的,因此我喜欢这样的想法,即当标记嵌套不正确时,我至少可以处理一些事情,而不是异常:)无论如何,再次感谢;)您也可以将行号(在
    $data
    中的索引)保留在每个标记上,以便您可以回过头来,在错误消息中指出标记打开的位置,关闭标记匹配。这可能会帮助您更详细地处理错误条件。
    Array
    (
        [tag] => av_one_third
        [children] => Array
            (
                [0] => Array
                    (
                        [tag] => av_icon_box
                        [children] => Array
                            (
                            )
                    )
                [1] => Array
                    (
                        [tag] => av_button
                        [children] => Array
                            (
                            )
                    )
                [2] => Array
                    (
                        [tag] => av_icon_box
                        [children] => Array
                            (
                            )
                    )
            )
    )