
本教程详细介绍了如何使用php将复杂的树形数组结构高效地扁平化为简洁的列表数组。通过递归遍历树的每个节点,提取关键数据并移除层级信息,最终生成一个按id排序的、易于处理的扁平化数组。文章提供了清晰的代码示例和注意事项,帮助开发者理解并实现数据结构的转换。
在PHP开发中,我们经常会遇到将数据组织成树形结构(例如菜单、评论回复、组织架构等)的需求。然而,在某些场景下,例如将数据存储到数据库、进行全局搜索或需要线性处理数据时,我们又需要将这种树形结构“反向”扁平化回一个简单的列表数组。本文将深入探讨如何高效地实现这一转换过程。
为了更好地理解扁平化过程,我们首先来看一下涉及的两种数据结构:
1. 原始扁平数组(构建树的源数据)
这是一个典型的扁平数组,每个元素包含 id、parent_id 和 name 字段,通过 parent_id 字段建立了层级关系。parent_id 为 0 的节点通常表示根节点。
立即学习“PHP免费学习笔记(深入)”;
$sourceArray = [
['id' => 1, 'parent_id' => 0, 'name' => 'id1'],
['id' => 2, 'parent_id' => 1, 'name' => 'id2'],
['id' => 3, 'parent_id' => 1, 'name' => 'id3'],
['id' => 4, 'parent_id' => 0, 'name' => 'id4'],
['id' => 5, 'parent_id' => 2, 'name' => 'id5'],
['id' => 6, 'parent_id' => 3, 'name' => 'id6'],
['id' => 7, 'parent_id' => 0, 'name' => 'id7'],
['id' => 8, 'parent_id' => 3, 'name' => 'id8'],
['id' => 9, 'parent_id' => 4, 'name' => 'id9'],
['id' => 10, 'parent_id' => 9, 'name' => 'id10'],
];2. 待扁平化的树形数组
这是由上述扁平数组通过某种构建树的函数转换而来的树形结构。它通过 children 键来表示子节点,形成了嵌套的层级关系。需要注意的是,根节点通常没有 parent_id 字段,其 parent_id 在扁平化后应被视为 0。
$tree = [
[
"id" => 1,
"name" => "id1",
"children" => [
[
"id" => 2,
"parent_id" => 1,
"name" => "id2",
"children" => [
["id" => 5, "parent_id" => 2, "name" => "id5"]
]
],
[
"id" => 3,
"parent_id" => 1,
"name" => "id3",
"children" => [
["id" => 6, "parent_id" => 3, "name" => "id6"],
["id" => 8, "parent_id" => 3, "name" => "id8"]
]
]
]
],
[
"id" => 4,
"name" => "id4",
"children" => [
[
"id" => 9,
"parent_id" => 4,
"name" => "id9",
"children" => [
["id" => 10, "parent_id" => 9, "name" => "id10"]
]
]
]
],
["id" => 7, "name" => "id7", "children" => []]
];3. 期望的扁平化结果数组
扁平化后的目标是将上述树形结构还原成类似于 sourceArray 的形式,但通常会按照 id 进行排序,并且确保每个节点都包含 id、parent_id 和 name 字段。
// 期望的输出(按ID排序)
[
['id' => 1, 'parent_id' => 0, 'name' => 'id1'],
['id' => 2, 'parent_id' => 1, 'name' => 'id2'],
['id' => 3, 'parent_id' => 1, 'name' => 'id3'],
['id' => 4, 'parent_id' => 0, 'name' => 'id4'],
['id' => 5, 'parent_id' => 2, 'name' => 'id5'],
['id' => 6, 'parent_id' => 3, 'name' => 'id6'],
['id' => 7, 'parent_id' => 0, 'name' => 'id7'],
['id' => 8, 'parent_id' => 3, 'name' => 'id8'],
['id' => 9, 'parent_id' => 4, 'name' => 'id9'],
['id' => 10, 'parent_id' => 9, 'name' => 'id10'],
]将树形结构扁平化的核心思想是深度优先遍历(DFS)。我们通过递归函数遍历树的每一个节点,提取其核心数据(id, name, parent_id),并将其添加到最终的扁平化列表中。children 键在提取数据时将被忽略,因为它只用于表示层级关系。
此函数是递归处理树形结构的关键。它接收当前层级的节点数组和通过引用传递的扁平化结果数组。
/**
* 递归地将树形节点扁平化为列表。
*
* @param array $treeNodes 当前层级的树形节点数组。
* @param array $flatList 引用传递,用于累积扁平化后的节点列表。
* @return array 扁平化后的节点列表。
*/
function flattenTreeNodes(array $treeNodes, array &$flatList = []): array
{
foreach ($treeNodes as $node) {
// 提取当前节点的核心数据
// 使用 ?? 运算符确保 parent_id 存在,如果不存在则默认为 0 (适用于根节点)
$nodeData = [
'id' => $node['id'],
'parent_id' => $node['parent_id'] ?? 0,
'name' => $node['name'],
];
// 将当前节点数据添加到扁平化列表中
$flatList[] = $nodeData;
// 如果当前节点有子节点,则递归调用自身处理子节点
if (isset($node['children']) && is_array($node['children']) && !empty($node['children'])) {
flattenTreeNodes($node['children'], $flatList);
}
}
return $flatList;
}函数逻辑说明:
为了使最终的扁平化数组更规范和易于使用,我们通常会对其进行排序(例如按 id 升序),并重置数组的数字索引。
这个函数作为入口点,负责调用递归函数并对结果进行后处理。
/**
* 将完整的树形结构扁平化为按ID排序的列表数组。
*
* @param array $tree 完整的树形结构数组。
* @return array 扁平化并排序后的列表数组。
*/
function getFlatArrayFromTree(array $tree): array
{
$flatArray = [];
// 调用递归函数进行扁平化
flattenTreeNodes($tree, $flatArray);
// 对扁平化后的数组按 'id' 字段进行升序排序
usort($flatArray, static function (array $node1, array $node2) {
// PHP 7+ 的飞船运算符 (<=>) 简洁地实现三向比较
return ($node1['id'] <=> $node2['id']);
});
// 重置数组的数字键,确保从 0 开始连续索引
return array_values($flatArray);
}函数逻辑说明:
将上述函数与示例数据结合,可以得到一个完整的可运行代码:
<?php
/**
* 递归地将树形节点扁平化为列表。
*
* @param array $treeNodes 当前层级的树形节点数组。
* @param array $flatList 引用传递,用于累积扁平化后的节点列表。
* @return array 扁平化后的节点列表。
*/
function flattenTreeNodes(array $treeNodes, array &$flatList = []): array
{
foreach ($treeNodes as $node) {
// 提取当前节点的核心数据
// 使用 ?? 运算符确保 parent_id 存在,如果不存在则默认为 0 (适用于根节点)
$nodeData = [
'id' => $node['id'],
'parent_id' => $node['parent_id'] ?? 0,
'name' => $node['name'],
];
// 将当前节点数据添加到扁平化列表中
$flatList[] = $nodeData;
// 如果当前节点有子节点,则递归调用自身处理子节点
if (isset($node['children']) && is_array($node['children']) && !empty($node['children'])) {
flattenTreeNodes($node['children'], $flatList);
}
}
return $flatList;
}
/**
* 将完整的树形结构扁平化为按ID排序的列表数组。
*
* @param array $tree 完整的树形结构数组。
* @return array 扁平化并排序后的列表数组。
*/
function getFlatArrayFromTree(array $tree): array
{
$flatArray = [];
// 调用递归函数进行扁平化
flattenTreeNodes($tree, $flatArray);
// 对扁平化后的数组按 'id' 字段进行升序排序以上就是将树形数组扁平化为列表数组的PHP教程的详细内容,更多请关注php中文网其它相关文章!
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号