Php:将平面数组转换为树状结构 [英] Php: Converting a flat array into a tree like structure

查看:111
本文介绍了Php:将平面数组转换为树状结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要有关数组转换的帮助.我有一个看起来像这样的平面数组:

I need help with an array conversion. I have a flat array that looks like this:

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之类的结构的标签.我现在需要的是将该数组转换为类似于以下结构的嵌套数组:

The values of this array are actually tags from a xml like structure. what I now need is to convert this array into a nested array that resembles the following structure:

[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_button标记没有我尝试的xml解析函数的结束标记抛出.

Is there an easy way to do this? My first Idea was to convert the array to an xml string and use one of phps native XML functions but the problem is that self closing tags are not labeled as such. In the case above the fact that the av_button tag has no closing tag throws of the xml parsing functions i tried.

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

Some additional requirements: - elements can hold any number of children - final array must maintain correct order

是否存在任何可以轻松解决此问题的智能阵列排序功能? 希望对此有任何提示!

Are there any smart array sorting functions that could easily solve this? Would appreciate any hints on this!

最诚挚的问候:)

推荐答案

您的数组具有典型的平面结构,用于编码层次结构.但前提是您要在那里修复错误.

Your array has a typical flat structure encoding a hierarchy. But only if you fix the error in there.

然后,它基本上与下面的PHP代码类似,其工作原理包括异常,这些异常告诉数据中的错误,以便您可以修复数据(您可以在本网站上找到类似的示例,例如,参见 如何将一系列父子关系转换为层次树? ):

It basically then works like in the following list with PHP codes, including exceptions telling where errors are in the data so that you can fix your data (you can find similar examples on this website e.g. see the linked questions in How can I convert a series of parent-child relationships into a hierarchical tree?):

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

  1. Initialize a root entry inside a tree array. There you can add children to.

$tree     = ['children' => []];

  • 在树中创建一个指针数组,该指针的第一个元素(级别0)指向树的根元素:

  • Create an array of pointers into the tree of which it's first element (level 0) points to the root element of the tree:

    $pointers = [&$tree];
    

  • 现在遍历数据内的每一行:

  • Now go over each line inside the data:

    foreach ($data as $index => $line) {
    

  • 确定该行是否关闭并存储该决定结果:

  • Decide whether the line closes and store that decisions result:

    $close = '/' === $line[0];
    

  • 存储指针的当前计数:

  • Store the current count of pointers:

    $count = count($pointers);
    

  • 如果该行没有关闭,请打开一个新元素,然后继续:

  • In case the line does not close, open a new element and continue:

    $pointers[$count]                   = ['tag' => $line, 'children' => []];
    $pointers[$count - 1]['children'][] = & $pointers[$count];
    continue;
    

  • 如果该行确实关闭了,请验证标记名是否匹配,如果匹配,请删除最后创建的指针:

  • In case the line does close instead, validate if the tagname is matches and if so, remove the last created pointer:

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

  • 像概述一样处理完所有行之后,可以删除所有指针:

  • After all lines have been processed like outlined all pointers can be removed:

    unset($pointers);
    

  • 结果是可以在根节点的第一个子代中找到的数组.可以将其分配给变量,然后删除不需要的引用:

  • The result is the array that can be found in the first children in the root node. It can be assigned to a variable and the not needed references can be deleted then:

    $result = &$tree['children'][0];
    unset($tree);
    print_r($result);
    

  • 如果数据正确,则示例输出:

    If the data is correct, it exemplary outputs:

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

    这篇关于Php:将平面数组转换为树状结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆