矩阵算法实现:合并人员行并为明细行添加序号
解决你的矩阵算法难题:生成带汇总行和序号明细的消费报告
我看你现在的代码思路有点绕,其实换个先按人员分组的方式,能更清晰地解决重复P行和明细序号的问题。咱们一步步来修正:
现有代码的核心问题
makeHeaderDetail给每一行都生成了P行,导致同一人员有多个重复的P行,而且没有计算总消费额removeDuplicate的key逻辑有问题,错误地合并了D行(因为它把D|日期作为key,会把同一日期的不同消费合并)
正确的实现思路
先把所有数据按人员分组,然后对每个人员的分组:
- 计算该人员的总消费额,生成唯一的P行
- 遍历该人员的所有消费明细,为每一行添加递增的序号,生成D行
完整修正后的代码
const chai = require('chai') const chaiAsPromised = require("chai-as-promised") chai.use(chaiAsPromised) const expect = chai.expect, should = chai.should // 按人员分组,把同一人的所有消费记录归为一组 const groupByPerson = (data) => { return data.reduce((groups, row) => { const name = row[0]; if (!groups[name]) { groups[name] = []; } groups[name].push(row); return groups; }, {}); }; // 生成最终的报告数组 const groupReport = (obj) => { const result = []; // 第一步:按人员分组 const personGroups = groupByPerson(obj); // 遍历每个人员的分组 Object.entries(personGroups).forEach(([name, rows]) => { // 计算总消费:将所有价格转为数字后求和 const total = rows.reduce((sum, row) => sum + Number(row[3]), 0); // 添加P行:['P', 姓名, 总费用(字符串格式)] result.push(['P', name, String(total)]); // 遍历明细行,生成带序号的D行 rows.forEach((row, index) => { // 从原始行中提取日期、物品、价格,添加序号(index+1) const [_, date, item, price] = row; result.push(['D', String(index + 1), date, item, price]); }); }); return result; }; // 输入数据 const groupReportInput = [ ['Claudia', 'Monday', 'Ice cream', '5'], ['Claudia', 'Tuesday', 'Ice cream', '5'], ['Claudia', 'Thursday', 'Cake', '10'], ['Anna', 'Monday', 'Ice cream', '5'], ['Beatrice', 'Tuesday', 'Cake', '10'], ['Beatrice', 'Wednesday', 'Cake', '10'], ['Beatrice', 'Thursday', 'Ice cream', '5'], ['Beatrice', 'Thursday', 'Biscuit', '7'] ]; // 期望输出数据 const groupReportOutput = [ ['P', 'Claudia', '20'], ['D', '1', 'Monday', 'Ice cream', '5'], ['D', '2', 'Tuesday', 'Ice cream', '5'], ['D', '3', 'Thursday', 'Cake', '10'], ['P', 'Anna', '5'], ['D', '1', 'Monday', 'Ice cream', '5'], ['P', 'Beatrice', '32'], ['D', '1', 'Tuesday', 'Cake', '10'], ['D', '2', 'Wednesday', 'Cake', '10'], ['D', '3', 'Thursday', 'Ice cream', '5'], ['D', '4', 'Thursday', 'Biscuit', '7'] ]; // 执行测试 const doIt = groupReport(groupReportInput); console.log(doIt); describe('groupReport', () => { it('should return an array with merged P rows and ordered D rows', () => { expect(doIt).to.deep.equal(groupReportOutput); }); });
关键改进点说明
- 分组逻辑:用
reduce把同一人员的所有消费记录聚在一起,从根源避免了重复P行的问题 - 总费用计算:在每个人员的分组内直接求和,确保总金额准确
- 明细序号:利用
forEach的索引index,通过index+1生成从1开始的连续序号 - 去掉异步:原代码的
async是多余的,因为所有操作都是同步的,去掉后测试逻辑更简洁
这样运行代码就能完全匹配你期望的输出啦!
内容的提问来源于stack exchange,提问作者Viet
相关产品推荐
相关产品推荐

