如何将Expense对象数组归约为按日期聚合的精简数组?
解决Expense数组按日期合并分类的问题
问题分析
你当前的代码逻辑存在两个核心问题:
- 当找到相同日期的对象时,没有修改原有的对象,而是直接将合并后的新对象追加到数组末尾,导致原对象和新对象同时存在,出现重复日期条目
- 初始值设置了
[{ 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
相关产品推荐
相关产品推荐

