
在许多业务场景中,我们经常会遇到具有层级关系的数据,例如公司的组织架构、用户的推荐系统(多级下线)、文件目录等。这些数据通常以嵌套的JSON对象或数组形式表示。本教程将以一个典型的用户层级存款数据为例,演示如何计算每个层级的存款总额。
假设我们有一个表示用户及其下线的层级结构,每个用户节点包含一个deposit字段表示其存款金额,以及一个可选的children数组,表示其直接下线。层级深度可能不固定,但通常会有最大限制(例如,最多5层)。我们的目标是得到一个数组,其中每个元素代表对应层级的存款总和。
以下是示例数据结构片段:
[
{
"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": [] }
]期望的输出结果是一个数组,例如 [300, 300, 300, 300],表示第一层总和、第二层总和、第三层总和等。
立即学习“Java免费学习笔记(深入)”;
初学者在处理此类问题时,可能会尝试使用简单的迭代或递归,但容易陷入将所有存款扁平化收集的误区。例如,以下代码会收集所有节点的存款,而不是按层级汇总:
// 假设 Children 类型已定义
// const [userDeposit, setUserDeposit] = useState<number[]>([]); // 在React等框架中可能这样使用
const iterateOfChildrenDepositWrong = (
children: any[], // 简化类型为any[]
result: number[] = [],
): void => {
children.forEach((node: any) => {
result.push(node.deposit); // 这里直接将存款添加到结果数组
if (node.children && node.children.length > 0) {
iterateOfChildrenDepositWrong(node.children, result);
}
});
// setUserDeposit(result); // 在实际应用中可能会更新状态
};
// 调用示例
// let allDeposits: number[] = [];
// iterateOfChildrenDepositWrong(initialData, allDeposits);
// console.log(allDeposits); // 输出将是所有存款的扁平列表,如 [100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 0]上述代码的问题在于,它在遍历每个节点时,直接将其deposit值添加到同一个result数组中。当递归调用处理子节点时,子节点的存款也会被添加到这个result数组中,导致最终得到的是所有层级存款的混合列表,无法区分每个层级的总和。要实现按层级汇总,我们需要在每次处理一个层级时,计算该层级的总和,并将其作为一个独立的元素添加到结果数组中。
为了按层级汇总存款,我们需要一种方法来在处理完一个层级的所有节点后,再进入下一个层级。这本质上是一种广度优先遍历(BFS)的思想,但通过递归也可以优雅地实现。核心思路是:
以下是实现按层级汇总存款的JavaScript函数:
// 简化后的示例数据,只包含deposit和children字段
let hierarchicalData = [
{
"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 levelWiseDeposits: number[] = []; // 用于存储最终结果的数组
/**
* 递归函数,用于按层级汇总存款
* @param children 当前层级的节点数组
* @param result 存储每个层级总和的数组(通过引用传递)
*/
function iterateOfChildrenDeposit(children: any[], result: number[]): void {
let currentLevelSum = 0; // 当前层级的存款总和
let nextLevelChildren: any[] = []; // 存储下一层级的所有子节点
// 遍历当前层级的所有节点
children.forEach((node: any) => {
currentLevelSum += node.deposit; // 累加当前节点的存款
// 如果当前节点有子节点,则将其添加到下一层级列表中
if (node.children && node.children.length > 0) {
nextLevelChildren = nextLevelChildren.concat(node.children);
}
});
// 将当前层级的总和添加到结果数组中
result.push(currentLevelSum);
// 如果下一层级存在节点,则递归调用自身处理下一层级
if (nextLevelChildren.length > 0) {
iterateOfChildrenDeposit(nextLevelChildren, result);
}
// 递归终止条件:当nextLevelChildren为空时,表示没有更多层级
}
// 调用函数开始计算
iterateOfChildrenDeposit(hierarchicalData, levelWiseDeposits);
console.log('按层级汇总的存款:', levelWiseDeposits);
// 预期输出: [300, 300, 300, 300]通过采用递归与广度优先遍历思想相结合的方法,我们能够有效地按层级汇总嵌套数据结构中的数值。这种方法清晰地分离了不同层级的处理逻辑,确保了结果的准确性。理解并掌握这种处理层级数据的模式,对于开发涉及树形结构的应用至关重要。
以上就是深度解析:JavaScript中如何按层级汇总嵌套数据结构中的金额的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号