如何在JavaScript中按日期筛选并按天分组汇总成本数据
按天分组求和成本数据的解决方案
我来帮你搞定这个按ISO日期天维度分组求和成本的问题!先明确你的需求:把给定的带ISO日期的对象数组,按日期的“天”聚合,计算每天的总成本,最终得到预期的sumData数组。
先分析你现有代码的问题
你的代码逻辑存在几个关键缺陷:
- 未及时存入累加结果:当遇到不同日期时,你只是重置了
currentTotal,但没有把之前累加好的当天成本推入sumData数组,最后只push了最后一个日期的总和,导致结果缺失。 - 依赖数据顺序:你的逻辑是比较相邻元素的日期,如果原始数据不是按日期顺序排列的,分组求和会完全出错(比如某天的数据穿插在其他日期中间时)。
- 重置逻辑冗余:在else分支里,你先把
currentTotal设为0再赋值为当前item的成本,虽然结果没问题,但多了一步不必要的操作。
推荐的解决方案
我会用reduce结合对象映射的方式来实现,这种方式不管数据是否有序都能正确分组,逻辑更简洁健壮:
// 你的原始数据数组 const data = [ {id: 45, title: 'abo', cost: 10, recurrent: true, date: '2022-02-09T20:43:30.139Z'}, {id: 123, title: 'test 4', cost: 20, recurrent: false, date: '2022-02-09T20:43:30.139Z'}, {id: 125, title: 'test 3', cost: 50, recurrent: false, date: '2022-02-06T23:00:00.000Z'}, {id: 125, title: 'test 2', cost: 100, recurrent: false, date: '2022-02-05T10:00:00.000Z'}, {id: 125, title: 'test 1', cost: 122, recurrent: false, date: '2022-02-04T23:00:00.000Z'} ]; // 1. 先按日期排序(可选,但能让最终结果按日期顺序排列) const sortedData = [...data].sort((a, b) => new Date(a.date) - new Date(b.date)); // 2. 用reduce构建日期到总成本的映射 const dailyCostMap = sortedData.reduce((acc, item) => { // 将ISO日期格式化为YYYY-MM-DD的字符串,作为分组的唯一键 const dayKey = new Date(item.date).toISOString().split('T')[0]; // 累加当天成本:如果键已存在则累加,否则初始化为当前item的成本 acc[dayKey] = (acc[dayKey] || 0) + item.cost; return acc; }, {}); // 3. 提取映射中的值,得到最终的sumData数组 const sumData = Object.values(dailyCostMap); console.log(sumData); // 输出:[122, 222, 50, 30] —— 对应2022-02-04、2022-02-05、2022-02-06、2022-02-09的总成本
灵活调整结果顺序
如果你需要和你预期的[222,50,30](对应2022-02-05、2022-02-06、2022-02-09)一致,只需要:
- 按日期降序排序:把sort的回调改成
new Date(b.date) - new Date(a.date) - 过滤掉2022-02-04的数据:在reduce时加判断,或者提取values后slice掉第一个元素
示例代码:
// 降序排序 const sortedDataDesc = [...data].sort((a, b) => new Date(b.date) - new Date(a.date)); const dailyCostMapDesc = sortedDataDesc.reduce((acc, item) => { const dayKey = new Date(item.date).toISOString().split('T')[0]; // 跳过2022-02-04的数据 if (dayKey !== '2022-02-04') { acc[dayKey] = (acc[dayKey] || 0) + item.cost; } return acc; }, {}); const sumData = Object.values(dailyCostMapDesc).reverse(); console.log(sumData); // 输出:[222,50,30]
内容的提问来源于stack exchange,提问作者florian_drupal
相关产品推荐
相关产品推荐

