2013-03-03 111 views
0

我需要数组转换帮助。我有一个看起来像这样的平面阵列:Php:将平面阵列转换为树状结构

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解析函数。

一些额外的要求: - 元素可以任意数量的子 的 - 最后的阵列必须保持正确的顺序

是否有任何智能数组排序,可以轻松解决这个功能呢? 希望对此有任何提示!

此致:)

+0

你确定你不是最好使用[XML Parser](http://www.php.net/manual/en/refs.xml.php)?否则,你需要创建一个递归函数。 – kjetilh 2013-03-03 18:46:49

回答

1

你的阵列具有编码层次结构的典型平面结构。但是,只有当你解决了那里的错误。

它基本上就像下面的PHP代码一样工作,包括例外情况,告诉数据中的错误,以便修复数据(您可以在本网站上找到类似示例,例如参见How can I convert a series of parent-child relationships into a hierarchical tree?中的链接问题) :

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

谢谢!不知道为什么这实际上是封闭的,但这正是我一直在寻找:) – Kriesi 2013-03-04 09:29:52

+0

它可能是封闭的,因为它不清楚你到目前为止做了什么。更好地展示你已经尝试了什么,以及你在哪里碰到障碍,所以问题更加清晰。顺便说一句:XML解决方案更简单,但它不会给你阵列。 – hakre 2013-03-04 09:31:53

+0

谢谢!实际上,我已经取消了xml解决方案,但是由于带有标签的初始数组是由用户输入生成的,所以我喜欢这样的想法,即当标签嵌套错误而不是异常时,我至少有一些工作要做: 反正,谢谢再次;) – Kriesi 2013-03-04 09:46:43