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

如何将Expense对象数组归约为按日期聚合的精简数组?

解决Expense数组按日期合并分类的问题

问题分析

你当前的代码逻辑存在两个核心问题:

  1. 当找到相同日期的对象时,没有修改原有的对象,而是直接将合并后的新对象追加到数组末尾,导致原对象和新对象同时存在,出现重复日期条目
  2. 初始值设置了[{ date: 0 }],这个无关对象会一直保留在结果中

正确实现方案

推荐使用对象映射的方式处理,查找日期的效率更高(O(1)),代码逻辑更清晰:

interface Expense {
  price: number;
  date: number;
  category: {
    name: string;
  };
}

// 示例输入数据
const months: Expense[] = [
  {date: 1, price: 300, category: {name: 'Bills'}},
  {date: 1, price: 20, category: {name: 'Entertainment'}},
  {date: 2, price: 40, category: {name: 'Health'}},
  {date: 6, price: 5, category: {name: 'Food'}},
  {date: 6, price: 50, category: {name: 'Health'}}
];

// 用对象按日期分组存储
const groupedByDate = months.reduce((acc, curr) => {
  const targetDate = curr.date;
  if (acc[targetDate]) {
    // 日期已存在,直接添加分类属性
    acc[targetDate][curr.category.name] = curr.price;
  } else {
    // 日期不存在,创建新对象
    acc[targetDate] = {
      date: targetDate,
      [curr.category.name]: curr.price
    };
  }
  return acc;
}, {} as Record<number, { date: number; [key: string]: number }>);

// 将对象的值转换为数组,得到最终结果
const newData = Object.values(groupedByDate);

输出结果

[
  { date: 1, Bills: 300, Entertainment: 20 },
  { date: 2, Health: 40 },
  { date: 6, Food: 5, Health: 50 }
]

另一种数组直接处理的方案(效率较低)

如果坚持用数组作为累加器,可以修改逻辑直接更新已存在的对象:

const newData = months.reduce((acc, curr) => {
  // 查找是否已有该日期的对象
  const existingItem = acc.find(item => item.date === curr.date);
  if (existingItem) {
    // 更新已有对象的分类属性
    existingItem[curr.category.name] = curr.price;
  } else {
    // 新增日期对象
    acc.push({
      date: curr.date,
      [curr.category.name]: curr.price
    });
  }
  return acc;
}, [] as { date: number; [key: string]: number }[]);

这个方案用find方法查找数组中已有的日期对象,找到后直接修改该对象(因为对象是引用类型,修改会同步到数组中),避免了重复添加对象的问题,同时初始值设为空数组,移除了多余的{date:0}条目。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 01:57:41