You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JavaScript实现按年重置的月度累计求和?

问题:年度内月度累计求和(基于JavaScript reduce)

我有一个涵盖2010至2020年的每日数据集,需要将其处理为年度内逐月累加、新年度开始时重置累计的月度总和。目前已用reduce实现月度单独求和,但未完成年度内跨月累计,寻求解决方案。

数据集示例

const data = [
 {num: 3, date: "2010-01-01", month: "January", year: 2010}, 
 {num: 10, date: "2010-01-02", month: "January", year: 2010}, 
 {num: 2, date: "2010-01-03", month: "January", year: 2010},
 {num: 0.1, date: "2010-01-04", month: "January", year: 2010},
 {num: 0, date: "2010-01-05", month: "January", year: 2010},
 {num: 13, date: "2010-02-01", month: "February", year: 2010},
 {num: null, date: "2010-02-02", month: "February", year: 2010},
 {num: null, date: "2010-02-03", month: "February", year: 2010},
 {num: 2, date: "2010-02-04", month: "February", year: 2010},
 {num: 3, date: "2010-02-05", month: "February", year: 2010},
 {num: 0.1, date: "2010-03-01", month: "March", year: 2010},
 {num: 0.002, date: "2010-03-02", month: "March", year: 2010},
 {num: 4, date: "2010-03-03", month: "March", year: 2010},
 {num: 4.1, date: "2010-03-04", month: "March", year: 2010},
 {num: 6, date: "2010-03-05", month: "March", year: 2010},
 {num: 6.7, date: "2011-01-01", month: "January", year: 2011}, 
 {num: 2, date: "2011-01-02", month: "January", year: 2011}, 
 {num: 2.2, date: "2011-01-03", month: "January", year: 2011},
 {num: 3, date: "2011-01-04", month: "January", year: 2011},
 {num: null, date: "2011-01-05", month: "January", year: 2011},
 {num: 0, date: "2011-02-01", month: "February", year: 2011},
 {num: 0, date: "2011-02-02", month: "February", year: 2011},
 {num: 2.1, date: "2011-02-03", month: "February", year: 2011},
 {num: 0, date: "2011-02-04", month: "February", year: 2011},
 {num: 0, date: "2011-02-05", month: "February", year: 2011},
 {num: null, date: "2011-03-01", month: "March", year: 2011},
 {num: 2.1, date: "2011-03-02", month: "March", year: 2011},
 {num: 4, date: "2011-03-03", month: "March", year: 2011},
 {num: 9, date: "2011-03-04", month: "March", year: 2011},
 {num: 7.8, date: "2011-03-05", month: "March", year: 2011},
];

当前代码(月度单独求和)

data.reduce((acc, curr) => {
    if (curr.num === null ) return acc
    for ( const e of acc) {
        if (e.year === curr.year && e.month === curr.month) {
            e.totalSum += curr.num
            return acc
        }
    }
    const y = {
        year: curr.year, 
        month: curr.month, 
        total: curr.num
    }
    return state.concat([y]) // 此处state应为acc,属于拼写错误
}, [])

当前输出

[
 {year: 2010, month: "January", total: 15.1},
 {year: 2010, month: "February", total: 18}, 
 {year: 2010, month: "March", total: 14.202},
 {year: 2011, month: "January", total: 13.9},
 {year: 2011, month: "February", total: 2.1 },
 {year: 2011, month: "March", total: 22.9},
]

期望输出

[
 {year: 2010, month: "January", total: 15.1},
 {year: 2010, month: "February", total: 33.1}, //15.1+18
 {year: 2010, month: "March", total: 47.302}, //15.1+18+14.202
 {year: 2011, month: "January", total: 13.9}, // 新年度重置累计
 {year: 2011, month: "February", total: 16 }, // 13.9 + 2.1
 {year: 2011, month: "March", total: 38.9}, //13.9 + 2.1 + 22.9
]

解决方案

方法:分两步用reduce处理

先聚合月度单独总和,再基于此计算年度内累计值,逻辑清晰易理解,适合学习reduce的使用场景。

步骤1:修正并计算月度单独总和

先修正原代码的拼写错误,同时统一字段名,得到各年月的单独求和结果:

// 计算各月单独总和
const monthlySums = data.reduce((acc, curr) => {
  if (curr.num === null) return acc;
  
  // 查找当前年月已存在的条目
  const existingItem = acc.find(item => item.year === curr.year && item.month === curr.month);
  
  if (existingItem) {
    // 累加当前数值到对应月份
    existingItem.monthTotal += curr.num;
  } else {
    // 新增当月条目
    acc.push({
      year: curr.year,
      month: curr.month,
      monthTotal: curr.num
    });
  }
  return acc;
}, []);

步骤2:计算年度内累计值

遍历月度总和数组,对同一年份的条目逐月累加,新年度重置累计:

// 计算年度内累计总和
const cumulativeResult = monthlySums.reduce((acc, curr) => {
  // 获取上一条记录,判断是否同一年份
  const lastEntry = acc[acc.length - 1];
  let cumulativeTotal = curr.monthTotal;
  
  if (lastEntry && lastEntry.year === curr.year) {
    // 同一年份,累加上月累计值
    cumulativeTotal += lastEntry.total;
  }
  
  acc.push({
    year: curr.year,
    month: curr.month,
    total: cumulativeTotal
  });
  return acc;
}, []);

额外处理:确保数据有序

如果原始数据集的日期是乱序的,需要先按日期排序,否则月度顺序混乱会导致累计错误:

// 按日期排序(可选,若数据集已按时间顺序排列可省略)
data.sort((a, b) => new Date(a.date) - new Date(b.date));

最终结果

执行上述代码后,cumulativeResult即可得到期望的年度内累计月度总和。


内容的提问来源于stack exchange,提问作者vaitaka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 01:05:52