I'm trying to reduce the an array of Expenses:
interface Expense { price: number, date: number, category: { name: string } }
So that I get an array of objects where each date is unique and the properties are added on if a new one is found.
So basically I want to turn:
[{date: 1, price: 300, category: 'Bills'}, {date: 1, price: 20, category: 'Entertainment'}]
into:
[ {date: 1, Bills: 300, Entertainment: 20 } ]
Here's what I have, except it's creating a new object if the date already exists, instead of adding to the current object:
const newData = months.reduce(
(acc, curr) => {
for (let i = 0; i < acc.length; i++) {
if (curr.date === acc[i].date) {
return [
...acc,
{
...acc[i],
date: curr.date,
[curr.category.name]: curr.price,
},
];
}
}
return [
...acc,
{
date: curr.date,
[curr.category.name]: curr.price,
},
];
},
[{ date: 0 }]
);
So my output is this instead:
Array(10) [
{ date: 0 }, { date: 0, Entertainment: 100 }, { date: 1, Entertainment: 30 }, { date: 1, Entertainment: 30, School: 80 },
{ date: 2, Health: 40 }, { date: 3, Food: 200 }, { date: 4, Transportation: 70 }, { date: 5, Bills: 900 }, { date: 6, Food: 5 },
{ date: 6, Food: 5, Health: 50 }
]
I'm super close, but I'm not sure how to fix
A possible approach would programmatically create/aggregate an object where same date
values would be utilized as grouping keys for data item's which are related by date
. The single reduce
task which gets used on that behalf either does access and aggregate a new condensed data-structure or it does create and assign and aggregate it. Creating and/or accessing gets achieved via the nullish coalescing assignment operator / ??=
whereas the aggregation is taken care of by Object.assign
. From the intermediate result of an index of key-value pairs only the values (the new condensed data-structures) are of interest. Thus one has to pass the result of the reduce
task to Object.values
.
const sampleData = [{
date: 1, price: 300, category: 'Bills',
}, {
date: 1, price: 20, category: 'Entertainment',
}, {
date: 2, price: 200, category: 'Bills',
}, {
date: 2, price: 30, category: 'Entertainment',
}];
console.log(
Object
.values(
sampleData
.reduce((index, { date, price: value, category: key }) => {
Object.assign(
// - create and assign or access object.
(index[date] ??= { date }),
// - aggregate the `date` specific object.
{ [ key ]: value },
);
return index;
}, {})
)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }