我有一个这样的清单:
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'),
)
但是更大,所以我需要一种有效的方法将它变成像这样的结构树:
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',
)
)
)
我不能使用嵌套集之类的东西或像becoas之类的东西我可以在我的数据库中添加左右值。 有任何想法吗?
答案 0 :(得分:55)
oke这就是我解决它的方式:
$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;
}
答案 1 :(得分:40)
小修复:)
$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;
}
答案 2 :(得分:12)
Thunderstriker's variant的另一个返工 - 一个函数中的所有逻辑:
function buildTree($flat, $pidKey, $idKey = null)
{
$grouped = array();
foreach ($flat as $sub){
$grouped[$sub[$pidKey]][] = $sub;
}
$fnBuilder = function($siblings) use (&$fnBuilder, $grouped, $idKey) {
foreach ($siblings as $k => $sibling) {
$id = $sibling[$idKey];
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'=>'a'],
['id'=>101, 'parentID'=>100, 'name'=>'a'],
['id'=>102, 'parentID'=>101, 'name'=>'a'],
['id'=>103, 'parentID'=>101, 'name'=>'a'],
];
$tree = buildTree($flat, 'parentID', 'id');
print_r($tree);
答案 3 :(得分:9)
以下是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]);
}
使用:
$tree = createTree($flat);
答案 4 :(得分:6)
我创建了一个不寻常的('基于时间的'而不是递归)但多维排序函数,它可以遍历数组直到没有任何孤儿。这里的功能是:
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] );
}
}
}
}
建议:数组中每个元素的键必须是元素本身的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' ),
);
用法:该函数需要$ a(数组),$ parent_key(保存父亲id的列名),$ children_key(列的名称)孩子们会动起来)。它什么都不返回(数组通过引用更改)。例如:
treeze( $ARRAY, 'father', 'children' );
echo "<pre>"; print_r( $ARRAY );
答案 5 :(得分:1)
执行此操作的一种方法是使用递归函数,该函数首先查找列表的所有底部值,并将它们添加到新数组中。然后对于每个新id,在该id上使用相同的函数,获取返回的数组并将其填充到该项的新子数组中。最后,您将返回新阵列。
我不会为你完成所有的工作,但函数的参数看起来像是:
function recursiveChildren($ items_array,$ parent_id = 0)
基本上,它会找到所有父项为0的那些,然后对于每一个,它会找到所有具有该id作为父项的那些,以及每个那些......等等。
最终结果应该是您正在寻找的。 p>
答案 6 :(得分:1)
这三通方法有什么原因不起作用?我没有做任何测试来比较速度与一些递归解决方案,但它似乎更直接。如果您的初始数组已经与作为键的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;
}
答案 7 :(得分:1)
//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>";
答案 8 :(得分:0)
更简单的版本:
function build_tree(&$items, $parentId = null) {
$treeItems = [];
foreach ($items as $idx => $item) {
if((empty($parentId) && empty($item['parent_id'])) || (!empty($item['parent_id']) && !empty($parentId) && $item['parent_id'] == $parentId)) {
$items[$idx]['children'] = build_tree($items, $items[$idx]['id']);
$treeItems []= $items[$idx];
}
}
return $treeItems;
}
build_tree($array);