如何用PHP将扁平数组转换为递归菜单式嵌套数组?
用PHP将扁平数组转换为递归嵌套数组
给定如下扁平数组数据(支持扩展更多层级):
[ [ "id" => "uuid-1", "createdAt" => "2021-02-26T00:55:36.632Z", "name" => "Webprovise Corp", "parentId" => "0" ], [ "id" => "uuid-2", "createdAt" => "2021-02-25T10:35:32.978Z", "name" => "Stamm LLC", "parentId" => "uuid-1" ], [ "id" => "uuid-3", "createdAt" => "2021-02-25T15:16:30.887Z", "name" => "Blanda, Langosh and Barton", "parentId" => "uuid-1" ], [ "id" => "uuid-4", "createdAt" => "2021-02-25T06:11:47.519Z", "name" => "Price and Sons", "parentId" => "uuid-2" ], [ "id" => "uuid-5", "createdAt" => "2021-02-25T13:35:57.923Z", "name" => "Hane - Windler", "parentId" => "uuid-3" ], [ "id" => "uuid-6", "createdAt" => "2021-02-26T01:41:06.479Z", "name" => "Vandervort - Bechtelar", "parentId" => "uuid-3" ], [ "id" => "uuid-7", "createdAt" => "2021-02-25T07:56:32.335Z", "name" => "Zieme - Mills", "parentId" => "uuid-2" ] ]
需要将其转换为包含childrens字段的递归嵌套数组,期望输出格式如下:
[ "uuid-1" => [ "id" => "uuid-1", "createdAt" => "2021-02-26T00:55:36.632Z", "name" => "Webprovise Corp", "childrens" => [ [ "id" => "uuid-2", "createdAt" => "2021-02-25T10:35:32.978Z", "name" => "Stamm LLC", "parentId" => "uuid-1", "childrens" => [ [ "id" => "uuid-4", "createdAt" => "2021-02-25T06:11:47.519Z", "name" => "Price and Sons", "parentId" => "uuid-2" ], [ "id" => "uuid-7", "createdAt" => "2021-02-25T07:56:32.335Z", "name" => "Zieme - Mills", "parentId" => "uuid-2" ] ] ], [ "id" => "uuid-3", "createdAt" => "2021-02-25T15:16:30.887Z", "name" => "Blanda, Langosh and Barton", "parentId" => "uuid-1", "childrens" => [ [ "id" => "uuid-5", "createdAt" => "2021-02-25T13:35:57.923Z", "name" => "Hane - Windler", "parentId" => "uuid-3" ], [ "id" => "uuid-6", "createdAt" => "2021-02-26T01:41:06.479Z", "name" => "Vandervort - Bechtelar", "parentId" => "uuid-3" ] ] ], ] ] ]
解决思路
- 第一步:将扁平数组转换为以
id为键的索引数组,快速通过parentId定位父节点,避免重复遍历查找,提升处理效率。 - 第二步:遍历所有节点,把每个节点添加到对应父节点的
childrens数组中;根节点(parentId为0)直接存入结果数组。 - 第三步:该逻辑自动支持任意多级子节点,无需额外递归处理,因为父节点的
childrens会被持续填充。
实现代码
function buildNestedTree(array $flatArray): array { // 构建以id为键的索引数组,同时初始化每个节点的childrens字段 $indexed = []; foreach ($flatArray as $item) { $item['childrens'] = []; $indexed[$item['id']] = $item; } $nestedTree = []; foreach ($indexed as $id => $item) { $parentId = $item['parentId']; if ($parentId === '0') { // 根节点直接加入结果集 $nestedTree[$id] = $item; } else { // 将当前节点挂载到父节点的childrens数组中 if (isset($indexed[$parentId])) { $indexed[$parentId]['childrens'][] = $item; } } } return $nestedTree; } // 示例调用 $flatData = [ ["id" => "uuid-1", "createdAt" => "2021-02-26T00:55:36.632Z", "name" => "Webprovise Corp", "parentId" => "0"], ["id" => "uuid-2", "createdAt" => "2021-02-25T10:35:32.978Z", "name" => "Stamm LLC", "parentId" => "uuid-1"], ["id" => "uuid-3", "createdAt" => "2021-02-25T15:16:30.887Z", "name" => "Blanda, Langosh and Barton", "parentId" => "uuid-1"], ["id" => "uuid-4", "createdAt" => "2021-02-25T06:11:47.519Z", "name" => "Price and Sons", "parentId" => "uuid-2"], ["id" => "uuid-5", "createdAt" => "2021-02-25T13:35:57.923Z", "name" => "Hane - Windler", "parentId" => "uuid-3"], ["id" => "uuid-6", "createdAt" => "2021-02-26T01:41:06.479Z", "name" => "Vandervort - Bechtelar", "parentId" => "uuid-3"], ["id" => "uuid-7", "createdAt" => "2021-02-25T07:56:32.335Z", "name" => "Zieme - Mills", "parentId" => "uuid-2"], ]; $nestedResult = buildNestedTree($flatData); // 打印格式化后的结果 echo '<pre>' . print_r($nestedResult, true) . '</pre>';
代码说明
- 先通过一次遍历生成索引数组,给每个节点初始化
childrens空数组,后续查找父节点的时间复杂度为O(1),大幅提升效率。 - 二次遍历完成节点挂载:根节点直接进入结果数组,子节点则添加到对应父节点的
childrens中,逻辑清晰且支持无限层级。 - 采用迭代式处理,避免了递归可能出现的深度限制问题,同时性能更优,适合处理大量数据。
内容的提问来源于stack exchange,提问作者May'Habit
相关产品推荐
相关产品推荐

