我希望通过匹配相同的日期字符串来减少对象数组,并将这些匹配日期的总数相加,然后将它们组合成一个对象。我可以将阵列放置成几千个项目,所以我试图增加(在可能的情况下)和复杂性。
// before
let objArr = [
{
date: '01/01/2018',
total: 1
},
{
date: '01/01/2018',
total: 2
},
{
date: '01/02/2018',
total: 3
},
{
date: '01/02/2018',
total: 4
},
...
]
// final result
let finalArr = [
{
date: '01/01/2018',
total: 3
},
{
date: '01/02/2018',
total: 7
},
...
]
我似乎无法掌握使用reduce减少它们的习惯:
objArr.reduce((acc, obj) => {
acc.set(obj.date, (acc.get([obj.date]) || 0) + obj.total);
return acc;
}, new Map())
结果总是以错误的总数结尾,或者最后几个数组对象看起来像:
// bad output
badArray = [
...,
{
date: '01/02/2018',
total: 4
},
{
date: undefined,
total: NaN
},
{
date: undefined,
total: NaN
}
]
我编写了一个脚本来检查以确保date
和total
属性中的所有值都以它们所需的方式存在,但是我仍然遇到了错误的数组。这里的假设是我的reduce函数不正确。
答案 0 :(得分:3)
您的代码几乎正确。问题是您将Map键设置为日期,但是尝试通过传递带有日期而不是单独日期的数组来get
。
您可能正在使用:acc.get([obj.date])
(acc.get(obj.date)
(没有[ ]
)时使用
let objArr = [{date: '01/01/2018',total: 1},{date: '01/01/2018',total: 2},{date: '01/02/2018',total: 3},{date: '01/02/2018',total: 4},]
let s = objArr.reduce((acc, obj) => {
// not acc.get([obj.date]) !
acc.set(obj.date, (acc.get(obj.date) || 0) + obj.total);
return acc;
}, new Map())
// turn the Map into something that will display:
console.log([...s.entries()].map(([date, total]) => ({date, total})))
答案 1 :(得分:0)
我认为Mark Meyer的答案很好,但这也是另一个选择,它使用空数组作为初始值而不是Map(始终保持输入的原始结构):
let objArr = [{date: '01/01/2018',total: 1},{date: '01/01/2018',total: 2},{date: '01/02/2018',total: 3},{date: '01/02/2018',total: 4},];
const result = objArr.reduce((acc, obj) => {
const existingObj = acc.find((o) => o.date === obj.date);
if (existingObj) {
existingObj.total += obj.total;
} else {
acc.push(obj);
}
return acc;
}, []);
console.log(result);
请注意,使用空数组作为初始值的好处是它可以保持输入的原始结构(因此,您不必随后遍历生成的Map并将其转换为对象数组)。 :)