php 从数组列表创建数组树
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4196157/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
create array tree from array list
提问by Thunderstriker
i have a list like this:
我有一个这样的清单:
array(
array(id=>100, parentid=>0, name=>'a'),
array(id=>101, parentid=>100, name=>'a'),
array(id=>102, parentid=>101, name=>'a'),
array(id=>103, parentid=>101, name=>'a'),
)
but way bigger so i need a efficient way to make this into a tree like structure like this:
但是要大得多,所以我需要一种有效的方法将其变成这样的树状结构:
array(
id=>100, parentid=>0, name=>'a', children=>array(
id=>101, parentid=>100, name=>'a', children=>array(
id=>102, parentid=>101, name=>'a',
id=>103, parentid=>101, name=>'a',
)
)
)
i cannot use things like nested set or things like that becoas i can add left and right values in my database. any ideas?
我不能使用嵌套集之类的东西,因为我可以在我的数据库中添加左右值。有任何想法吗?
回答by Thunderstriker
oke this is how i solved it:
好吧,这就是我解决它的方法:
$arr = array(
array('id'=>100, 'parentid'=>0, 'name'=>'a'),
array('id'=>101, 'parentid'=>100, 'name'=>'a'),
array('id'=>102, 'parentid'=>101, 'name'=>'a'),
array('id'=>103, 'parentid'=>101, 'name'=>'a'),
);
$new = array();
foreach ($arr as $a){
$new[$a['parentid']][] = $a;
}
$tree = createTree($new, array($arr[0]));
print_r($tree);
function createTree(&$list, $parent){
$tree = array();
foreach ($parent as $k=>$l){
if(isset($list[$l['id']])){
$l['children'] = createTree($list, $list[$l['id']]);
}
$tree[] = $l;
}
return $tree;
}
回答by arthur
small fix if you need more than 1 parentid[0] element :)
如果您需要 1 个以上的 parentid[0] 元素,请进行小修复:)
$arr = array(
array('id'=>100, 'parentid'=>0, 'name'=>'a'),
array('id'=>101, 'parentid'=>100, 'name'=>'a'),
array('id'=>102, 'parentid'=>101, 'name'=>'a'),
array('id'=>103, 'parentid'=>101, 'name'=>'a'),
);
$new = array();
foreach ($arr as $a){
$new[$a['parentid']][] = $a;
}
$tree = createTree($new, $new[0]); // changed
print_r($tree);
function createTree(&$list, $parent){
$tree = array();
foreach ($parent as $k=>$l){
if(isset($list[$l['id']])){
$l['children'] = createTree($list, $list[$l['id']]);
}
$tree[] = $l;
}
return $tree;
}
回答by Vasily
One more rework of Thunderstriker's variant- all the logic in one function:
Thunderstriker 变体的另一项重做- 一个函数中的所有逻辑:
/**
* @param $flatList - a flat list of tree nodes; a node is an array with keys: id, parentID, name.
*/
function buildTree(array $flatList)
{
$grouped = [];
foreach ($flatList as $node){
$grouped[$node['parentID']][] = $node;
}
$fnBuilder = function($siblings) use (&$fnBuilder, $grouped, $idKey) {
foreach ($siblings as $k => $sibling) {
$id = $sibling['id'];
if(isset($grouped[$id])) {
$sibling['children'] = $fnBuilder($grouped[$id]);
}
$siblings[$k] = $sibling;
}
return $siblings;
};
$tree = $fnBuilder($grouped[0]);
return $tree;
}
// Example:
$flat = [
['id' => 100, 'parentID' => 0, 'name' => 'root'],
['id' => 101, 'parentID' => 100, 'name' => 'ch-1'],
['id' => 102, 'parentID' => 101, 'name' => 'ch-1-1'],
['id' => 103, 'parentID' => 101, 'name' => 'ch-1-2'],
];
$tree = buildTree($flat, 'parentID', 'id');
echo json_encode($tree, JSON_PRETTY_PRINT);
Playground: https://www.tehplayground.com/xOqMQd11W96XljZV
回答by Pierre de LESPINAY
Here is my adaptation from arthur's rework:
这是我改编自亚瑟的返工:
/* Recursive branch extrusion */
function createBranch(&$parents, $children) {
$tree = array();
foreach ($children as $child) {
if (isset($parents[$child['id']])) {
$child['children'] =
$this->createBranch($parents, $parents[$child['id']]);
}
$tree[] = $child;
}
return $tree;
}
/* Initialization */
function createTree($flat, $root = 0) {
$parents = array();
foreach ($flat as $a) {
$parents[$a['parent']][] = $a;
}
return $this->createBranch($parents, $parents[$root]);
}
Use:
用:
$tree = createTree($flat);
回答by Marco Panichi
I created an unusual ('while-based' instead of recursive) but multidimensionalsorting function that walk the array until there aren't any orphans. Here the function:
我创建了一个不寻常的('while-based' 而不是递归)但多维排序函数,它遍历数组直到没有任何孤儿。这里的功能:
function treeze( &$a, $parent_key, $children_key )
{
$orphans = true; $i;
while( $orphans )
{
$orphans = false;
foreach( $a as $k=>$v )
{
// is there $a[$k] sons?
$sons = false;
foreach( $a as $x=>$y )
if( isset($y[$parent_key]) and $y[$parent_key]!=false and $y[$parent_key]==$k )
{
$sons=true;
$orphans=true;
break;
}
// $a[$k] is a son, without children, so i can move it
if( !$sons and isset($v[$parent_key]) and $v[$parent_key]!=false )
{
$a[$v[$parent_key]][$children_key][$k] = $v;
unset( $a[$k] );
}
}
}
}
Recommendation:the key of each element of the array has to be the id fo the element itself. Example:
建议:数组中每个元素的键必须是元素本身的 id。例子:
$ARRAY = array(
1 => array( 'label' => "A" ),
2 => array( 'label' => "B" ),
3 => array( 'label' => "C" ),
4 => array( 'label' => "D" ),
5 => array( 'label' => "one", 'father' => '1' ),
6 => array( 'label' => "two", 'father' => '1' ),
7 => array( 'label' => "three", 'father' => '1' ),
8 => array( 'label' => "node 1", 'father' => '2' ),
9 => array( 'label' => "node 2", 'father' => '2' ),
10 => array( 'label' => "node 3", 'father' => '2' ),
11 => array( 'label' => "I", 'father' => '9' ),
12 => array( 'label' => "II", 'father' => '9' ),
13 => array( 'label' => "III", 'father' => '9' ),
14 => array( 'label' => "IV", 'father' => '9' ),
15 => array( 'label' => "V", 'father' => '9' ),
);
Usage:the function need $a (the array), $parent_key (the name of the column where the id of the father is saved), $children_key (the name of the column where the children will be move). It returns nothing (the array is changed by reference). Example:
用法:该函数需要$a(数组)、$parent_key(保存父亲id的列名)、$children_key(孩子将要移动的列名)。它不返回任何内容(数组通过引用更改)。例子:
treeze( $ARRAY, 'father', 'children' );
echo "<pre>"; print_r( $ARRAY );
回答by Pham
//if order by parentid, id
$arr = array(
array('id'=>100, 'parentid'=>0, 'name'=>'a'),
array('id'=>101, 'parentid'=>100, 'name'=>'a'),
array('id'=>102, 'parentid'=>101, 'name'=>'a'),
array('id'=>103, 'parentid'=>101, 'name'=>'a'),
);
$arr_tree = array();
$arr_tmp = array();
foreach ($arr as $item) {
$parentid = $item['parentid'];
$id = $item['id'];
if ($parentid == 0)
{
$arr_tree[$id] = $item;
$arr_tmp[$id] = &$arr_tree[$id];
}
else
{
if (!empty($arr_tmp[$parentid]))
{
$arr_tmp[$parentid]['children'][$id] = $item;
$arr_tmp[$id] = &$arr_tmp[$parentid]['children'][$id];
}
}
}
unset($arr_tmp);
echo '<pre>'; print_r($arr_tree); echo "</pre>";
回答by psyon
Is there any reason this three pass method wouldn't work? I didn't do any tests to compare speed to some of the recursive solutions, but it seemed more straight forward. If your initial array is already associative with the IDs being the key, then you can skip the first foreach()
.
这三遍方法是否有任何原因不起作用?我没有做任何测试来比较一些递归解决方案的速度,但它似乎更直接。如果您的初始数组已经与作为键的 ID 关联,那么您可以跳过第一个foreach()
.
function array_tree(&$array) {
$tree = array();
// Create an associative array with each key being the ID of the item
foreach($array as $k => &$v) {
$tree[$v['id']] = &$v;
}
// Loop over the array and add each child to their parent
foreach($tree as $k => &$v) {
if(!$v['parent']) {
continue;
}
$tree[$v['parent']]['children'][] = &$v;
}
// Loop over the array again and remove any items that don't have a parent of 0;
foreach($tree as $k => &$v) {
if(!$v['parent']) {
continue;
}
unset($tree[$k]);
}
return $tree;
}
回答by DampeS8N
One way to do this is with a recursive function that first finds all the bottom values of the list, adding them to a new array. Then for each new id, you use the same function on that id, taking the returned array and stuffing it in that item's new children array. Finally, you return your new array.
一种方法是使用递归函数,该函数首先查找列表的所有底部值,并将它们添加到新数组中。然后,对于每个新 id,您对该 id 使用相同的函数,获取返回的数组并将其填充到该项目的新子数组中。最后,返回新数组。
I won't do all the work for you, but the function's parameters will look something like:
我不会为你做所有的工作,但函数的参数看起来像:
function recursiveChildren($items_array, $parent_id = 0)
函数递归儿童($items_array,$parent_id = 0)
Essentially, it'll find all the ones with parent of 0, then for each of those it'll find all the ones with that id as the parent, and for each of those.. so on.
本质上,它会找到所有父项为 0 的那些,然后对于每一个它会找到所有具有该 id 作为父项的那些,并且对于其中的每一个......依此类推。
The end result should be what you are looking for.
最终结果应该是您正在寻找的。