树形结构数据汇总问题:如何正确计算每个节点自身金额及子节点金额总和并展示
树形结构数据汇总问题:如何正确计算每个节点自身金额及子节点金额总和并展示
我看了你的代码和输出结果,问题主要出在两个关键点上:
- 只有根节点的
amount被赋值了,所有子节点的amount都没从amountMap里获取,所以显示undefined - 因为子节点的
amount都是undefined,递归计算totalAmount的时候子节点贡献的总和都是0,导致根节点的总金额只算了自己的500,没加上所有子节点的金额
咱们来一步步修复:
1. 核心问题分析
你原本只在rootSponsors.forEach()循环里给根节点设置了amount,但所有子节点完全没处理这一步,导致它们的amount都是undefined;而递归计算总金额时,子节点的贡献值都是0,最终根节点的总金额自然不对。
2. 修复方案
咱们需要给所有节点统一设置自身金额,然后保留原本正确的递归计算逻辑即可。
修改后的完整代码(标注修改点)
<script> // Function to transform the flat list of sponsors into a tree structure function buildSponsorTree(sponsors, amn) { console.log(sponsors, amn); const sponsorMap = new Map(); // Map each sponsor by its ID for easy access sponsors.forEach(sponsor => { sponsorMap.set(sponsor.id, {...sponsor, children: []}); }); // --- 新增:给所有节点统一设置自身amount --- const amountMap = new Map(); amn.forEach(amount => { // 注意:如果后端返回的_id是字符串,要转成数字和sponsor.id匹配 amountMap.set(Number(amount._id), amount); }); // 遍历所有节点,初始化自身金额 sponsorMap.forEach(sponsor => { const amt = amountMap.get(sponsor.id); sponsor.amount = amt ? amt.totalAmount : 0; }); // --- 新增结束 --- const rootSponsors = []; // Build the tree structure where sponsor_id is the child and id is the parent sponsors.forEach(sponsor => { if(sponsor.sponsor_id !== -1) { const parent = sponsorMap.get(sponsor.sponsor_id); if(parent) { parent.children.push(sponsorMap.get(sponsor.id)); } } else { rootSponsors.push(sponsorMap.get(sponsor.id)); } }); function calculateTotalAmount(sponsor) { // Calculate total amount for this sponsor let total = sponsor.amount || 0; // Recursively calculate the total for all children sponsor.children.forEach(child => { total += calculateTotalAmount(child); }); // Add the total amount to the sponsor sponsor.totalAmount = total; return total; } // --- 修改:移除原根节点单独赋值逻辑,直接计算所有根节点的总金额 --- rootSponsors.forEach(sponsor => { calculateTotalAmount(sponsor); }); // --- 修改结束 --- return rootSponsors; } // Function to recursively render the sponsor tree function renderSponsorTree(sponsors) { let html = '<ul>'; sponsors.forEach(sponsor => { console.log(sponsor.totalAmount, sponsor.amount); html += ` <li> <strong>${sponsor.name}</strong> (ID: ${sponsor.id}) Amount - ${sponsor.amount} (TotalAmount - ${sponsor.totalAmount}) ${sponsor.children.length > 0 ? renderSponsorTree(sponsor.children) : ''} </li> `; }); html += '</ul>'; return html; } // Fetch sponsor data from the server and process it into a tree structure window.onload = function() { axios.get("http://localhost:5000/show").then((response) => { const sponsors = response.data[0]; const amn = response.data[1]; const sponsorTree = buildSponsorTree(sponsors, amn); const treeHtml = renderSponsorTree(sponsorTree); console.log(sponsorTree); document.getElementById("show").innerHTML = treeHtml; }).catch((error) => { console.error('Error fetching data:', error); alert('Error loading sponsor data.'); }); }; </script>
修复后效果
- 所有节点的
amount都会显示自身实际金额(无数据则显示0),不会再出现undefined - 每个节点的
totalAmount会等于自身金额 + 所有子节点的总金额总和,也就是该节点及其所有后代的金额总和 - 根节点Raj的
totalAmount会正确计算为500加上所有子节点的金额总和,符合你的需求
额外注意事项
请确认后端返回的amount数组中,_id字段和sponsor的id字段类型一致(比如都是数字),如果_id是字符串类型,要在构建amountMap时转成数字(代码中已添加Number(amount._id)的处理)。
备注:内容来源于stack exchange,提问作者Tamanna
相关产品推荐
相关产品推荐

