Reputation: 107
So I have an array of objects that looks like this.
const myArray = [
{
values: [
{ date: "2018-11-02", "value1": 3, "value2": 5 },
{ date: "2018-11-01", "value1": 8, "value2": 9 },
{ date: "2018-10-31", "value1": 4, "value2": 10 },
],
customer: "Customer One"
},
{
values: [
{ date: "2018-11-02", "value1": 3 },
{ date: "2018-11-01", "value1": 5 },
{ date: "2018-10-31", "value1": 8 },
],
customer: "Customer Two"
}
];
All values of an object should be summed(by date) and then result as the value for the customer in the new object
What I want is it to look like this:
result = [
{ date: "2018-11-02", "Customer One": 8, "Customer Two": 3 },
{ date: "2018-11-01", "Customer One": 17, "Customer Two": 5 },
{ date: "2018-10-31", "Customer One": 14, "Customer Two": 8 },
]
I have working code for this but it feels way too complicated for what I need but I can't wrap my head around an easier way for some reason.
Here's my code (also on codesandbox: https://codesandbox.io/s/zvlpm167x):
const myArray = [
{
values: [
{ date: "2018-11-02", "value1": 3, "value2": 5 },
{ date: "2018-11-01", "value1": 8, "value2": 9 },
{ date: "2018-10-31", "value1": 4, "value2": 10 },
],
customer: "Customer One"
},
{
values: [
{ date: "2018-11-02", "value1": 3 },
{ date: "2018-11-01", "value1": 5 },
{ date: "2018-10-31", "value1": 8 },
],
customer: "Customer Two"
}
];
const flatArray = myArray.flat();
const sumObjectKeysExceptDate = object => Object.keys(object).reduce((sum, key) => {
if (!Number.isNaN(parseInt(object[key], 10)) && key !== 'date') {
return sum + parseInt(object[key], 10);
}
return sum;
}, 0);
const result = flatArray
.reduce((acc, row) => [...acc, ...row.values.map(value => ({ [row.customer]: sumObjectKeysExceptDate(value), date: value.date }))], [])
.reduce((acc, row) => {
if (acc.find(innerrow => innerrow.date === row.date)) {
return acc.map((innerrow) => {
if (innerrow.date === row.date) {
return { ...innerrow, ...row };
}
return innerrow;
});
}
return [...acc, row];
}, []);
console.log(result)
Upvotes: 1
Views: 129
Reputation: 28445
Try following
date
as key and corresponding resulting object as value. And using Object.values
get the final resultArray.reduce
on outer array and for each value of inner array, check whether the entry for date exists or not in object. If it exists update it else create a new entry in object.customer
name key.const myArray = [{values: [{ date: "2018-11-02", "value1": 3, "value2": 5 },{ date: "2018-11-01", "value1": 8, "value2": 9 },{ date: "2018-10-31", "value1": 4, "value2": 10 },],customer: "Customer One"},{values: [{ date: "2018-11-02", "value1": 3 },{ date: "2018-11-01", "value1": 5 },{ date: "2018-10-31", "value1": 8 },],customer: "Customer Two"}];
let result = Object.values(myArray.reduce((a,c) => {
c.values.forEach(({date, ...rest}) => {
a[date] = a[date] || {date};
a[date][c.customer] = Object.values(rest).reduce((d,e) => d + e);
});
return a;
}, {}));
console.log(result);
Upvotes: 1