从PHP中的平面数组构build一棵树

我环顾了互联网,还没有find我要找的东西。 我有一个平面数组,每个元素包含一个“id”和“parent_id”。 每个元素只有一个父亲,但可能有多个孩子。 如果parent_id = 0,则认为它是根级别的项目。 我试图让我的平板数组到一棵树。 我发现的其他样本只是将元素复制到父项,但原始项目仍然存在。

编辑

起始数组的每个元素都是从单独的XML文件中读取的。 如果父文件没有父文件,则文件本身的值为0。 键实际上是string。

我很抱歉,以前的困惑。 希望这更清楚:

/编辑

我的起始arrays:

排列
 (
     [_319_] =>arrays
         (
             [id] => 0
             [parent_id] => 0
         )

     [_320_] =>arrays
         (
             [id] => _320_
             [parent_id] => 0
         )

     [_321_] =>arrays
         (
             [id] => _321_
             [parent_id] => _320_
         )

     [_322_] =>数组
         (
             [id] => _322_
             [parent_id] => _321_
         )

     [_323_] =>arrays
         (
             [id] => _323_
             [parent_id] => 0
         )

     [_324_] =>arrays
         (
             [id] => _324_
             [parent_id] => _323_
         )

     [_325_] =>arrays
         (
             [id] => _325_
             [parent_id] => _320_
         )
 ) 

树形成后的结果数组:

排列
 (
     [_319_] =>arrays
         (
             [id] => _319_
             [parent_id] => 0
         )

     [_320_] =>arrays
         (
             [id] => _320_
             [parent_id] => 0
             [children] =>数组
                 (
                     [_321_] =>arrays
                         (
                             [id] => _321_
                             [parent_id] => _320_
                             [children] =>数组
                                 (
                                     [_322_] =>数组
                                         (
                                             [id] => _322_
                                             [parent_id] => _321_
                                         )
                                 )
                         )
                     [_325_] =>arrays
                         (
                             [id] => _325_
                             [parent_id] => _320_
                         )
                 )
     [_323_] =>arrays
         (
             [id] => _323_
             [parent_id] => 0
             [children] =>数组
                 (
                     [_324_] =>arrays
                         (
                             [id] => _324_
                             [parent_id] => _323_
                         )
                 )
         )

任何帮助/指导,非常感谢!

我到目前为止的一些代码:


        函数buildTree(数组&$元素,$ parentId = 0){
         $ branch = array();

         foreach($元素为$元素){
             if($ element ['parent_id'] == $ parentId){
                 $ children = $ this-> buildTree($ elements,$ element ['id']);
                 if($ children){
                     $ element ['children'] = $ children;
                 }
                 $ branch [] = $ element;
             }
         }

        返回$分支;
     }

你在那里忘了unset()

 function buildTree(array &$elements, $parentId = 0) { $branch = array(); foreach ($elements as $element) { if ($element['parent_id'] == $parentId) { $children = buildTree($elements, $element['id']); if ($children) { $element['children'] = $children; } $branch[$element['id']] = $element; unset($elements[$element['id']]); } } return $branch; } 

由ImmortalFirefly的解决scheme正在工作,但是,正如mrded指出的,它不拯救没有孩子的父母。 我编辑了这个function来解决这个问题:

 function buildTree(array &$elements, $parentId = 0) { $branch = array(); foreach ($elements as &$element) { if ($element['parent_id'] == $parentId) { $children = buildTree($elements, $element['id']); if ($children) { $element['children'] = $children; } $branch[$element['id']] = $element; unset($element); } } return $branch; } 

我可以看到逻辑,除此之外的结果:

 Array ( [0] => Array ( [id] => 0 [parent_id] => 0 ) [1] => Array ( [id] => 1 [parent_id] => 0 ) 

恕我直言,是parent_id = o,不应该[1]在这里的[0]的孩子?

无论如何,参考救援:

 $tree = array(); foreach($inputarray as $item){ if(!isset($tree[$item['id']])) $tree[$item['id']] = array(); $tree[$item['id']] = array_merge($tree[$item['id']],$item); if(!isset($tree[$item['parent_id']])) $tree[$item['parent_id']] = array(); if(!isset($tree[$item['parent_id']]['children'])) $tree[$item['parent_id']]['children'] = array(); $tree[$item['parent_id']]['children'][] = &$tree[$item['id']]; } $result = $tree[0]['children']; unset($tree); print_r($result); 

因为你已经滥用了0作为一个“魔术”数字作为根和一个现有的ID,我们现在有recursion在ID = 0分支。 在$tree[$item['parent_id']]['children'][] = &$tree[$item['id']]; if($item['parent_id']!=$item['id'])之前添加if($item['parent_id']!=$item['id']) $tree[$item['parent_id']]['children'][] = &$tree[$item['id']]; 可以防止,但不是很漂亮。

这适用于我:

 $index=array(); $tree=array(); foreach ($ori as $key=>$var) { $var=array_shift($ori); if ($var['id']==0) $var['id']=$key; if ((string)$var['parent_id']==='0') { $tree[$key]=$var; $index[$key]=&$tree[$key]; } else if (isset($index[$var['parent_id']])) { if (!isset($index[$var['parent_id']]['children'])) $index[$var['parent_id']]['children']=array(); $index[$var['parent_id']]['children'][$key]=$var; $index[$key]=&$index[$var['parent_id']]['children'][$key]; } else { array_push($ori,$var); } } unset($index); print_r($tree); 

你可以使用这个函数(parent_id,id,title)构build一个稍微不同的源数组:

 $q = mysql_query("SELECT id, parent_id, name FROM categories"); while ($r = mysql_fetch_row($q)) { $names[$r[0]] = $r[2]; $children[$r[0]][] = $r[1]; } function render_select($root=0, $level=-1) { global $names, $children; if ($root != 0) echo '<option>' . strrep(' ', $level) . $names[$root] . '</option>'; foreach ($children[$root] as $child) render_select($child, $level+1); } echo '<select>'; render_select(); echo '</select>'; 
  1. 更高效的层次体系

虽然这是一个老问题,但我会在这里发表我的答案:

 /* assuming top level pid = 0 */ $rows = array ( array ( 'id' => 1, 'pid' => 0 ), /* ... */ ); /* make id become array key */ $rows = array_column ( $rows, null, 'id' ); foreach ( $rows as $key => $val ) { if ( $val ['pid'] ) { if ( isset ( $rows [$val ['pid']] )) { $rows [$val ['pid']]['children'][] = &$rows [$key]; } } } foreach ( $rows as $key => $val ) { if ( $val ['pid'] ) unset ( $rows [$key] ); } 

array_column是PHP 5.5,但你可以轻松创build自己的。

你想要在MySQL中存储和加载分层数据,因为我应该解决一些问题。 我假设第一个数组代表直接从数据库中取得的数据?

它看起来像你试图使用邻接模型来组织你的数据到层次结构。 还有其他的方法来实现这个使用嵌套。 如果你不从数据库中获取这些数据,那么这可能不是那么有用。

这个链接应该帮助你: http : //mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

这是我的解决scheme,理想情况下,如果我们假设顶级parent_id = 0:

 function MakeTree($arr){ $parents_arr=array(); foreach ($arr as $key => $value) { $parents_arr[$value['pid']][$value['id']]=$value; } $tree=$parents_arr['0']; $this->createTree($tree, $parents_arr); return $tree; } function createTree(&$tree, $parents_arr){ foreach ($tree as $key => $value) { if(!isset($value['children'])) { $tree[$key]['children']=array(); } if(array_key_exists($key, $parents_arr)){ $tree[$key]['children']=$parents_arr[$key]; $this->createTree($tree[$key]['children'], $parents_arr); } } } 

这是我的解决scheme,复制和优化其他解决scheme。

 function buildTree(array &$elements, $parentId = 0) { $branch = array(); foreach ($elements as $key => $element) { if ($element['parent_id'] == $parentId) { $children = $this->buildTree($elements, $key); if ($children) { $element['children'] = $children; } $branch[$key] = $element; unset($elements[$key]); } } return $branch; }