
在许多业务场景中,我们经常会遇到具有层级关系的数据,例如组织架构、推荐系统中的用户层级、文件目录结构等。本教程关注的是一个典型的推荐系统场景,其中用户可以有下级,下级也可以有自己的下级,形成一个多达五层的嵌套结构。每个用户节点都包含一个deposit(存款)字段。
我们的目标是计算并获取每个层级的用户总存款金额。例如,如果第一层有总计300的存款,第二层也有总计300的存款,以此类推,最终结果应为一个数组,如 [300, 300, 300, 300]。
以下是简化的数据结构示例:
let hierarchicalData = [
{
"id": "ddf86d60-a607-4a4e-a7f9-d96013ee7070",
"name": "Rick Rich",
"deposit": 100,
"children": [
{
"id": "25de2e98-eb2d-41f4-b225-3069f942b284",
"name": "Rick Rich",
"deposit": 100,
"children": [
{
"id": "376b202e-d44f-4402-9560-8498c855d05e",
"name": "Rick Rich",
"deposit": 100,
"children": [
{ "deposit": 100 },
{ "deposit": 100 },
{ "deposit": 100 }
]
},
{ "deposit": 100, "children": [] },
{ "deposit": 100, "children": [] }
]
},
{ "deposit": 100, "children": [] },
{ "deposit": 100, "children": [] }
]
},
{ "deposit": 100, "children": [] },
{ "deposit": 0, "children": [] }
];在这个结构中,最外层的数组代表第一层用户。每个用户对象中的 children 数组则代表其下一层级的用户。
初学者在处理这类问题时,常会尝试使用简单的遍历和递归来收集所有存款,但这种方法往往会导致数据扁平化,无法区分不同层级的金额。
例如,以下代码片段展示了一种常见的错误尝试:
// 错误的尝试示例
const iterateOfChildrenDepositIncorrect = (
children: any[], // 假设 Children 类型包含 deposit 和 children
result: number[] = [],
): void => {
children.forEach((node: any) => {
result.push(node.deposit); // 直接将存款添加到结果数组
if (node.children && node.children.length > 0) {
iterateOfChildrenDepositIncorrect(node.children, result); // 递归处理子节点
}
});
// 在实际应用中,result 会被更新到状态或返回
// setUserDeposit(result);
};
let incorrectResult = [];
iterateOfChildrenDepositIncorrect(hierarchicalData, incorrectResult);
console.log(incorrectResult); // 输出所有存款的扁平列表,如 [100, 100, 100, 100, 100, 100, ...]这段代码的问题在于,它将所有层级的 deposit 值都简单地添加到同一个 result 数组中。虽然它能收集所有存款,但无法提供每个层级的总和,因为 result 数组中的元素没有层级信息。我们需要的是一个表示每个层级总和的数组,而不是所有个体存款的列表。
要实现按层级汇总,我们需要一种机制来在处理当前层级时,收集所有子节点以便在下一轮递归中处理,同时计算当前层级的总和。这可以通过一种类似于广度优先搜索(BFS)的递归方法来实现。
核心思想是:
以下是实现按层级汇总存款的递归函数:
let hierarchicalDataSimplified = [
{
"deposit": 100,
"children": [
{
"deposit": 100,
"children": [
{
"deposit": 100,
"children": [
{ "deposit": 100 },
{ "deposit": 100 },
{ "deposit": 100 }
]
},
{ "deposit": 100, "children": [] },
{ "deposit": 100, "children": [] }
]
},
{ "deposit": 100, "children": [] },
{ "deposit": 100, "children": [] }
]
},
{ "deposit": 100, "children": [] },
{ "deposit": 0, "children": [] }
];
let resultByLevel = []; // 用于存储每个层级总存款的数组
/**
* 递归函数,用于按层级汇总存款金额
* @param {Array<Object>} children - 当前层级的节点数组
* @param {Array<number>} result - 存储各层级总金额的数组
*/
function iterateOfChildrenDeposit(children, result) {
let nextLevelChildren = []; // 存储下一层级的所有子节点
let currentLevelDepositSum = 0; // 当前层级的存款总和
// 遍历当前层级的所有节点
children.forEach((node) => {
currentLevelDepositSum += node.deposit; // 累加当前节点的存款
// 如果当前节点有子节点,则将它们添加到下一层级的集合中
if (node.children && node.children.length > 0) {
nextLevelChildren = nextLevelChildren.concat(node.children);
}
});
// 将当前层级的总存款添加到结果数组
result.push(currentLevelDepositSum);
// 如果下一层级有节点,则进行递归调用
if (nextLevelChildren.length > 0) {
return iterateOfChildrenDeposit(nextLevelChildren, result);
}
// 递归终止条件:没有下一层级节点
return;
}
// 调用函数开始处理
iterateOfChildrenDeposit(hierarchicalDataSimplified, resultByLevel);
console.log(resultByLevel); // 预期输出: [300, 300, 300, 300]interface ChildNode {
id?: string;
name?: string;
deposit: number;
bonus?: number;
referralChildDeposit?: number;
children?: ChildNode[];
}通过本教程,我们学习了如何利用递归函数有效地处理多层级嵌套数据结构,并按层级汇总特定数据(如存款金额)。关键在于在每次递归调用中,不仅要计算当前层级的数据,还要收集下一层级的全部节点,作为下一次递归的输入。这种方法确保了层级信息的独立性,避免了数据扁平化带来的混淆,是处理树形或图状数据结构的强大工具。理解并掌握这种递归模式,对于开发涉及复杂数据关系的应用程序至关重要。
以上就是多层级嵌套数据结构:按层级汇总存款金额的递归实现的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号