0

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

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_button 标签没有结束标签,我尝试了 xml 解析函数。

一些附加要求: - 元素可以包含任意数量的子元素 - 最终数组必须保持正确的顺序

是否有任何智能数组排序功能可以轻松解决这个问题?将不胜感激任何提示!

最好的祝福 :)

4

1 回答 1

1

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

然后它基本上可以像下面的 PHP 代码列表一样工作,包括告诉数据中错误在哪里的异常,以便您可以修复数据(您可以在此网站上找到类似的示例,例如查看如何转换系列中的链接问题将父子关系转化为层次树?):

  1. 初始化树数组中的根条目。在那里你可以添加孩子。

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

    $pointers = [&$tree];
    
  3. 现在遍历数据中的每一行:

    foreach ($data as $index => $line) {
    
  4. 决定线路是否关闭并存储该决定结果:

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

    $count = count($pointers);
    
  6. 如果该行没有关闭,请打开一个新元素并继续:

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

    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);
    
  8. 在按照概述的方式处理所有行之后,可以删除所有指针:

    unset($pointers);
    
  9. 结果是可以在根节点的第一个子节点中找到的数组。它可以分配给一个变量,然后可以删除不需要的引用:

    $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
                        (
                        )
                )
        )
)
于 2013-03-03T21:27:12.063 回答