I'm looking for a smart ES6 way to reduce array of objects into totals-by-property-object.
for a sample data:
const src = [{mon:1,tue:0,wed:3,thu:5,fri:7,sat:0,sun:4}, {mon:5,tue:3,wed:2,thu:0,fri:1,sat:0,sun:6}];
following code:
const res = src.reduce((totals,item) => Object.keys(item).forEach(weekday => totals[weekday] += item[weekday]),{})
throws an error:
Uncaught TypeError: Cannot read property 'mon' of undefined
even if reduce
is initialized with {mon:0, tue:0 ...}
instead of {}
.
Is there a non-for-loop solution?
p.s. expected output is an object where each property is a sum of array objects by that property, e.g. {mon:6, tue:3, wed:5, thu:5, fri:8, sat:0, sun:10}
in my case
const sum = values. reduce((accumulator, currentValue) => { return accumulator + currentValue; } , 0); As you can see, the reduce method executes the call back function multiple times. For each time, it takes the current value of the item in the array and sum with the accumulator.
If you use array reduce on an array without any elements and don't provide initialValue, it will throw a TypeError. If the array is empty and initialValue is provided, or the array has only one element and initialValue, the reduce method will return the same value without calling the callbackfn.
To sum a property in an array of objects:Call the reduce() method to iterate over the array. On each iteration increment the sum with the specific value. The result will contain the sum of the values for the specific property.
But did you know you can reduce them to objects as well? First, a quick overview of how reduce works. The reduce method receives two arguments: a function and an initial value. The function will run run for every value in the array, and receives two arguments as well: the accumulator, or acc , and the current value .
You need to return totals
as accumulator for reduce
.
If you have allways all days in the objects and you don't mind to mutate the first object, you could work without a start object.
const
src = [{ mon: 1, tue: 0, wed: 3, thu: 5, fri: 7, sat: 0, sun: 4 }, { mon: 5, tue: 3, wed: 2, thu: 0, fri: 1, sat: 0, sun: 6 }],
res = src.reduce((totals, item) =>
(Object.keys(item).forEach(d => totals[d] += item[d]), totals));
console.log(res);
You need to return totals
after you modify it:
const src = [{mon:1,tue:0,wed:3,thu:5,fri:7,sat:0,sun:4}, {mon:5,tue:3,wed:2,thu:0,fri:1,sat:0,sun:6}];
const res = src.reduce((totals, item) => {
Object.keys(item).forEach(weekday => totals[weekday] = (totals[weekday] || 0) + item[weekday]);
return totals;
}, {});
console.log(res);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With