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

JS使用reduce按日期聚合交易数据时不同MaterialID返回值一致问题

问题根因

你的问题核心是JavaScript引用类型的共享引用问题。你预先定义的dateObj是对象类型,属于引用值,你在初始化每个物料的monthlyVolume字段时直接将dateObj赋值过去,本质上所有物料的monthlyVolume都指向内存中同一个dateObj实例,任意物料修改月度统计的sum或count,都会直接修改全局的dateObj,最终所有物料的统计数据会完全同步。

解决方法

每次初始化新物料的月度统计数据时,创建一份全新的初始统计对象,避免所有物料共享同一个dateObj引用。

修正后代码

你可以单独封装一个获取初始月度统计对象的方法,每次初始化新物料时调用该方法拿到独立的统计对象:

// 每次调用返回独立的初始月度统计对象
const getInitMonthlyVolume = () => ({
  "Jan-20": { sum: 0, count: 0 },
  "Feb-20": { sum: 0, count: 0 },
  "Mar-20": { sum: 0, count: 0 },
  "Apr-20": { sum: 0, count: 0 }
})

let result = transactionData.reduce((acc, { MaterialID, TransactionDate, TransactionQuantity }) => {
    const date = dayjs(TransactionDate).format("MMM-YY");
    // 初始化物料时使用全新的统计对象
    const _material = acc[MaterialID] ??= { monthlyVolume: getInitMonthlyVolume() };
    _material.monthlyVolume[date].sum += parseFloat(TransactionQuantity);
    _material.monthlyVolume[date].count++;
    return acc;
}, {})

如果不想单独封装方法,也可以对原始dateObj做深拷贝实现相同效果:

let result = transactionData.reduce((acc, { MaterialID, TransactionDate, TransactionQuantity }) => {
    const date = dayjs(TransactionDate).format("MMM-YY");
    // 用JSON序列化的方式深拷贝dateObj,得到独立的初始统计对象
    const _material = acc[MaterialID] ??= { monthlyVolume: JSON.parse(JSON.stringify(dateObj)) };
    _material.monthlyVolume[date].sum += parseFloat(TransactionQuantity);
    _material.monthlyVolume[date].count++;
    return acc;
}, {})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 12:03:02