我正在尝试设置一个可以有多个级别的列表,使用parentId
来定义其父级。第一项parentId
为NULL。一些条目的例子:
id parentId name
1 NULL item1
2 NULL item2
3 1 item3
4 2 item4
5 3 item5
6 3 item6
所以,1和2是主要项目; 3是1的孩子; 4是2的孩子; 5是3的孩子(1本身的孩子); 6也是3的孩子(自己是1的孩子);等
我无法创建一个正确添加这些项目到正确级别的数组。它应该是这样的:
Array
(
[1] => Array
(
[name] => item1
[parentId] =>
[children] => Array
(
[3] => Array
(
[name] => item3
[parentId] => 1
[children] => Array
(
[5] => Array
(
[name] => item5
[parentId] => 3
)
[6] => Array
(
[name] => item6
[parentId] => 3
)
)
)
)
)
[2] => Array
(
[name] => item2
[parentId] =>
[children] => Array
(
[4] => Array
(
[name] => item4
[parentId] => 2
)
)
)
)
但是说我使用foreach()
查看了所有项目,然后我转到第5项。它的parentId是3,但是在那时,我不知道这个父3在数组中的位置,并且如何将孩子添加到该父母。
是否有一个技巧可以循环使用这些项目,并以正确的方式将它们全部放在适当位置?
答案 0 :(得分:11)
这是
// your original data as an array
$data = array(
array(
'id' => 1,
'parentId' => null,
'name' => 'item1'
),
array(
'id' => 2,
'parentId' => null,
'name' => 'item2'
),
array(
'id' => 3,
'parentId' => 1,
'name' => 'item3'
),
array(
'id' => 4,
'parentId' => 2,
'name' => 'item4'
),
array(
'id' => 5,
'parentId' => 3,
'name' => 'item5'
),
array(
'id' => 6,
'parentId' => 3,
'name' => 'item6'
),
);
递归函数
function buildTree( $ar, $pid = null ) {
$op = array();
foreach( $ar as $item ) {
if( $item['parentId'] == $pid ) {
$op[$item['id']] = array(
'name' => $item['name'],
'parentId' => $item['parentId']
);
// using recursion
$children = buildTree( $ar, $item['id'] );
if( $children ) {
$op[$item['id']]['children'] = $children;
}
}
}
return $op;
}
print_r( buildTree( $data ) );
/*
Array
(
[1] => Array
(
[name] => item1
[parentId] =>
[children] => Array
(
[3] => Array
(
[name] => item3
[parentId] => 1
[children] => Array
(
[5] => Array
(
[name] => item5
[parentId] => 3
)
[6] => Array
(
[name] => item6
[parentId] => 3
)
)
)
)
)
[2] => Array
(
[name] => item2
[parentId] =>
[children] => Array
(
[4] => Array
(
[name] => item4
[parentId] => 2
)
)
)
)
*/
答案 1 :(得分:1)
您应该使用项目的ID作为数组的键值,以便您可以通过以下方式向其父项添加项目:
$array[$parentID]['children'][$childID] = array();
答案 2 :(得分:1)
首先想到的只是你所拥有的平面版本:
array (
[0] => array(
'name' => 'item1',
'parent' => null
),
[1] => array(
'name' => 'item2',
'parent' => null
),
[3] => array(
'name' => 'item3',
'parent' => 0
),
[4] => array(
'name' => 'item4',
'parent' => 3
),
[5] => array(
'name' => 'item5',
'parent' => 1
),
[6] => array(
'name' => 'item6',
'parent' => 1
), );
基本上,您只能引用回父母。要找到所有孩子,你必须遍历数组。不过,初始设置时间会非常快。
第二个想到的,会涉及更多的设置,但后来访问时间会少得多:
array (
[0] => array(
'name' => 'item1',
'parent' => null,
'children' = array(3)
),
[1] => array(
'name' => 'item2',
'parent' => null
'children' = array(5, 6)
),
[3] => array(
'name' => 'item3',
'parent' => 0
'children' = array(4)
),
[4] => array(
'name' => 'item4',
'parent' => 3
'children' = array()
),
[5] => array(
'name' => 'item5',
'parent' => 1
'children' = array()
),
[6] => array(
'name' => 'item6',
'parent' => 1
'children' = array()
), );
在这一个中,您将所有子索引添加到父级。这需要更长的时间,但随后的访问时间会很快。当你弄清楚父母的时候,你只需要附加到父母的子阵列上。
第二种方法唯一真正的缺点是,如果要添加或删除项目,则必须记住返回并更新父项的子数组。
答案 3 :(得分:0)
您可能不再需要新的解决方案,但这对其他用户来说可能会派上用场:
// ! assuming $elements is built like: Array( id1 => Array(/*parameters*/) , ...)
function buildTree($elements) {
$e = Array(0 => Array()); // elements array
$r = Array(0 =>& Array()); // reference array
while ($elements) {// repeat till $elements is empty
// loop through (remaining) elements
foreach ($elements as $id => $element) {
$pid = $element['parentId']; // shortcut
if (array_key_exists($pid,$r)) { // parent already parsed -> can add this element
// use parent's reference to elements array to add this element ( $r[$pid] =& $e[path][to][$pid] )
$r[$pid] ['elements'][$id] = $element;
// create reference for this element using parent's reference
$r[$id] =& $r[$pid]['elements'][$id];
// unset current element in input array in order to limit while-loop
unset($elements[$id]);
}
}
}
return $e; // or whatever you need, the reference array can be useful if you need to fetch an element only knowing its id
}
它的作用:
$e
)并添加根元素(0/null
)$r
)声明一个数组,并已将$r[0]
引用到$e[0]
while
循环)的原因。&
之后的=
!)while
循环,你可以留下这个;))return
你需要什么!这种方法的好处是:
foreach
循环的数量(你可以根据目前的知识分配最多)$elements
)换句话说:它应该更快(我没有测试过它!),至少对于我使用它的更复杂的任务来说。