如何将扁平账户余额数组转换为层级化账户树?
实现扁平账户余额到层级账户树的转换
核心思路
把每个AccountBalance的codes数组看作一条层级路径,从根节点开始,沿着路径逐个查找或创建节点,同时累加每个节点的amountOut值,最终构建出完整的树结构。
步骤拆解
- 初始化根节点存储:用
Map存储顶级节点,键为codeType-code的组合,避免重复创建,同时实现快速查找。 - 遍历处理每一条余额数据:对每个
AccountBalance,沿着codes的层级依次推进:- 从当前层级的父节点集合开始(初始为根节点
Map) - 检查当前
codeType+code是否已存在对应节点:不存在则创建新节点并添加到父节点的subAccounts;存在则直接复用 - 将当前余额的
amountOut累加到该节点的amountOut字段 - 切换到下一层级,把当前节点作为父节点继续处理
- 从当前层级的父节点集合开始(初始为根节点
- 提取最终树结构:将根节点
Map的所有值转换为数组,就是最终的AccountTree。
TypeScript 实现代码
先补全基础类型定义(可根据实际场景调整):
// 账户层级代码结构 interface AccountCode { codeType: string; code: string; } // 扁平账户余额条目 interface AccountBalance { codes: AccountCode[]; amountOut: number; } // 层级化账户树节点 interface AccountTreeNode { codeType: string; code: string; amountOut: number; subAccounts: AccountTreeNode[]; } type AccountTree = AccountTreeNode[];
转换函数实现:
function convertToAccountTree(balances: AccountBalance[]): AccountTree { const rootNodes = new Map<string, AccountTreeNode>(); for (const balance of balances) { let currentParentMap = rootNodes; let currentParent: AccountTreeNode | null = null; for (const code of balance.codes) { const nodeKey = `${code.codeType}-${code.code}`; let node = currentParentMap.get(nodeKey); if (!node) { node = { codeType: code.codeType, code: code.code, amountOut: 0, subAccounts: [] }; currentParentMap.set(nodeKey, node); // 非根节点要添加到父节点的子列表中 currentParent?.subAccounts.push(node); } // 累加当前余额的出账金额 node.amountOut += balance.amountOut; // 切换到下一层级的父节点映射 const childMap = new Map<string, AccountTreeNode>(); node.subAccounts.forEach(child => { childMap.set(`${child.codeType}-${child.code}`, child); }); currentParentMap = childMap; currentParent = node; } } return Array.from(rootNodes.values()); }
输入输出验证示例
假设输入扁平数据:
const inputBalances: AccountBalance[] = [ { codes: [{ codeType: "LEVEL1", code: "A" }, { codeType: "LEVEL2", code: "A1" }], amountOut: 100 }, { codes: [{ codeType: "LEVEL1", code: "A" }, { codeType: "LEVEL2", code: "A2" }], amountOut: 200 }, { codes: [{ codeType: "LEVEL1", code: "B" }, { codeType: "LEVEL2", code: "B1" }], amountOut: 150 }, { codes: [{ codeType: "LEVEL1", code: "A" }, { codeType: "LEVEL2", code: "A1" }, { codeType: "LEVEL3", code: "A1-1" }], amountOut: 50 } ];
调用转换函数后,输出的层级树结构:
[ { codeType: "LEVEL1", code: "A", amountOut: 350, // 100+200+50 subAccounts: [ { codeType: "LEVEL2", code: "A1", amountOut: 150, // 100+50 subAccounts: [{ codeType: "LEVEL3", code: "A1-1", amountOut: 50, subAccounts: [] }] }, { codeType: "LEVEL2", code: "A2", amountOut: 200, subAccounts: [] } ] }, { codeType: "LEVEL1", code: "B", amountOut: 150, subAccounts: [{ codeType: "LEVEL2", code: "B1", amountOut: 150, subAccounts: [] }] } ]
关键细节说明
- 用
Map存储节点是为了O(1)时间复杂度的查找,避免同层级重复创建节点 - 每个节点的
amountOut会累加所有路径经过该节点的余额数据,符合层级汇总的需求 - 每一层级都会切换到当前节点的子节点映射,确保层级嵌套关系正确
内容的提问来源于stack exchange,提问作者Menyten
相关产品推荐
相关产品推荐

