从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>';
- 更高效的层次体系
虽然这是一个老问题,但我会在这里发表我的答案:
/* 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; }