矩阵算法需求:为对象数组中非Misc服务追加合计行
解决方案:带负合计的矩阵数据处理
我来帮你搞定这个需求,包括更新后的负合计输出要求。先梳理下核心需求:
- 保留原始数据的顺序,按用户分组
- 对每个用户的
Class和Drink服务(跳过Misc)计算金额总和,追加负数值的合计行到该用户数据的末尾
问题分析
你现有的代码逻辑存在偏差:它在每次迭代时都往数组里push合计行,而且累加方式不正确,导致输出结果的顺序和结构都不符合预期。我们需要调整思路,先保留原始数据,再单独计算总和,最后追加合计行。
修正后的代码
const calculateTotalRows = (data) => { // 按用户分组,同时存储原始数据和各服务的累计金额 const userGroups = data.reduce((acc, item) => { const [person] = item; if (!acc.has(person)) { acc.set(person, { original: [], totals: { Class: 0, Drink: 0 } }); } const group = acc.get(person); group.original.push(item); // 仅对Class和Drink服务累计金额 const [, service, , amount] = item; if (service === 'Class' || service === 'Drink') { group.totals[service] += Number(amount); } return acc; }, new Map()); // 组装最终结果:原始数据 + 负合计行 const result = []; userGroups.forEach(({ original, totals }) => { // 先加入当前用户的所有原始数据 result.push(...original); // 追加Class的负合计行(如果有相关数据) if (totals.Class !== 0) { result.push([original[0][0], 'Class', 'Total classes', `-${totals.Class}`]); } // 追加Drink的负合计行(如果有相关数据) if (totals.Drink !== 0) { result.push([original[0][0], 'Drink', 'Total drinks', `-${totals.Drink}`]); } }); return result; }; // 测试用例 const reqObj = [ ['Anna', 'Class', 'Cycling', '10'], ['Anna', 'Class', 'Boxing', '25'], ['Anna', 'Class', 'Climbing', '20'], ['Anna', 'Misc', 'Towel', '5'], ['Anna', 'Drink', 'Coffee', '3'], ['Anna', 'Drink', 'Tea', '4'], ['Beatrice', 'Drink', 'Tea', '4'], ['Beatrice', 'Class', 'Kickboxing', '25'], ['Beatrice', 'Misc', 'Lock', '20'], ['Beatrice', 'Misc', 'Towel', '5'] ]; const resObj = calculateTotalRows(reqObj); console.log(resObj);
代码解释
- 分组存储:使用
Map按用户分组,每个分组包含两个部分:original:保存该用户的所有原始数据条目,确保顺序和输入一致totals:累计Class和Drink服务的金额,跳过Misc
- 组装结果:遍历每个用户分组,先把原始数据加入结果数组,再根据累计金额追加负合计行。判断
totals是否为0是为了避免在用户没有对应服务时添加空的合计行 - 负数值处理:通过字符串模板
-${totals.Class}直接生成带负号的金额字符串,符合预期输出格式
输出结果
运行代码后会得到你需要的带负合计的结果,完全匹配更新后的预期输出。
内容的提问来源于stack exchange,提问作者Viet
相关产品推荐
相关产品推荐

