将平坦数组转换为多维数组

7
我有一个带有树形数据的数组(按父ID)。我想将其转换为多维数组。最好的方法是什么?是否有任何简短的函数可以实现这一点?
源数组:
$source = array(
    '0' => array(
            'Menu' => array(
                    'id' => 45
                    'name' => 'Home'
                    'parent_id' => 1
            )
    )
    '1' => array(
            'Menu' => array(
                    'id' => 47
                    'name' => 'Get started'
                    'parent_id' => 1
            )
    )
    '2' => array(
            'Menu' => array(
                    'id' => 72
                    'name' => 'Attributes'
                    'parent_id' => 71
            )
    )
    '3' => array(
            'Menu' => array(
                    'id' => 73
                    'name' => 'Headings'
                    'parent_id' => 71
            )
    )
    '4' => array(
            'Menu' => array(
                    'id' => 75
                    'name' => 'Links'
                    'parent_id' => 71
            )
    )
    '5' => array(
            'Menu' => array(
                    'id' => 59
                    'name' => 'Images'
                    'parent_id' => 75
            )
    )
    '6' => array(
            'Menu' => array(
                    'id' => 65
                    'name' => 'Lists'
                    'parent_id' => 75
            )
    )
);

一些父项在源数组中缺失。我希望那些缺少父项的条目成为根项。结果数组:
$result = array(
    '0' => array(
            'Menu' => array(
                    'id' => 45
                    'name' => 'Home'
                    'parent_id' => 1
            )
            'Children' => array()
    )
    '1' => array(
            'Menu' => array(
                    'id' => 47
                    'name' => 'Get started'
                    'parent_id' => 1
            )
            'Children' => array()
    )
    '2' => array(
            'Menu' => array(
                    'id' => 72
                    'name' => 'Attributes'
                    'parent_id' => 71
            )
            'Children' => array()
    )
    '3' => array(
            'Menu' => array(
                    'id' => 73
                    'name' => 'Headings'
                    'parent_id' => 71
            )
            'Children' => array()
    )
    '4' => array(
            'Menu' => array(
                    'id' => 75
                    'name' => 'Links'
                    'parent_id' => 71
            )
            'Children' => array(
                    '0' => array(
                        'Menu' => array(
                            'id' => 59
                            'name' => 'Images'
                            'parent_id' => 75
                        )
                        'Children' => array()
                    )
                    '1' => array(
                        'Menu' => array(
                            'id' => 65
                            'name' => 'Lists'
                            'parent_id' => 75
                        )
                        'Children' => array()
                   )
            )
     )
);

更新:已删除方括号。

1
第一个已经是多维数组了。多维意味着数组内部还有数组。 - animuson
这不是有效的PHP代码... [0] => array(... 或 ['Menu'] => array(... 这些是什么意思?我无法理解你的输入数据结构,所以我卡住了。 - Scott Evernden
@animuson:是的,你说得对。我没有表达清楚。但我认为我的意思很明确,不是吗?@SpawnCxy:是的。@Scott:这是有效的PHP代码。数组键可以是字符串,不仅仅是数字。 - bancer
你知道在CakePHP中,你可以将你的模型结构化为一个合适的MPTT树,附加Tree行为,然后只需执行$model->find('threaded')就能获得这个结果吗?http://book.cakephp.org/view/1339/Tree - deceze
@deceze:是的,我知道“threaded”的存在。我之前考虑过这个问题。但是,在我的问题中,源数组是对查询结果进行一些操作的结果。使用“threaded”数组进行操作并不容易。为了得到我需要的结果,需要进行太多的查询。因此,我只执行一个查询,将其缓存,并从中筛选出所需的内容,然后再进行格式化数组。 - bancer
3个回答

19

我认为 PHP 中没有内置的函数能够完成这个任务。

我尝试了下面的代码,它似乎可以按照你描述的方式准备嵌套数组:

$nodes = array();
$tree = array();
foreach ($source as &$node) {
  $node["Children"] = array();
  $id = $node["Menu"]["id"];
  $parent_id = $node["Menu"]["parent_id"];
  $nodes[$id] =& $node;
  if (array_key_exists($parent_id, $nodes)) {
    $nodes[$parent_id]["Children"][] =& $node;
  } else {
    $tree[] =& $node;
  }
}

var_dump($tree);

我曾在为我的演示"SQL和PHP中的分层模型"编写的PHP类中编写了一个类似的算法,但我使用的是对象而不是普通数组。


你太棒了!感谢你提供的解决方案和如此快速的回答!源数组是数据库查询的结果。 - bancer
1
请注意,如果父级在数据库结果集中出现在其子级之前,则该算法仅适用于父级。 - Bill Karwin

0

我编写了这个变量,考虑到根parent_id为0或缺失的情况。无论$source中父级在子级之前还是之后。

$source_by_id = array();
foreach ($source as &$row){
  $source_by_id[$row['id']] = &$row;
}
foreach ($source_by_id as $id => &$row){
  $source_by_id[ intval($row['parent_id']) ]['children'][$id] = &$row;
}
// remove cycling itself
unset($source_by_id[0]['children'][0]);

$result = $source_by_id[0]['children'];

结果数组键是适当的ID。享受!


0

我正在寻找一个带有分类的示例,来演示如何完成这个任务。这个示例假设父级始终具有父级ID为“0”。该示例使用ZF2。

没有引用或递归。关键在于输出,您需要查找[0]索引,并将parent_id指定为子项的索引。

$categoryLookup = $this->getCategoryLookup($associateById=true);

if ($assignedCategories) {          
    $categoryHeirarchy = array();
    foreach($assignedCategories as $assignedCategory) {
        $child = $categoryLookup[$assignedCategory->category_id];
        $parent = $categoryLookup[$child->parent_id];               
        $categoryHeirarchy[$child->parent_id][] = $categoryLookup[$child->category_id];
        $categoryHeirarchy[$parent->parent_id][$parent->category_id] = $categoryLookup[$parent->category_id];
    }           

    return $categoryHeirarchy;  
}


<h3>Categories</h3>
<dl class="dl-horizontal">
    <?php foreach($this->categoryHeirarchy[0] as $parent): ?>
        <dt><?php echo $this->escapeHtml($parent->name); ?></dt>
        <?php foreach($this->categoryHeirarchy[$parent->category_id] as $child): ?>
            <dd><?php echo $this->escapeHtml($child->name); ?></dd>
        <?php endforeach; ?>
    <?php endforeach; ?>                    
</dl>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接