Reputation: 73
I need to group by id and sum, but I need a new object for each result:
let data = [
{"id":"2018", "name":"test", "total":1200},
{"id":"2019", "name":"wath", "total":1500},
{"id":"2019", "name":"wath", "total":1800},
{"id":"2020", "name":"zooi", "total":1000},
]
I have this code that returns just one object with the result
let result = data.reduce(function (r, o) {
(r[o.id])?
r[o.id] += o.total:
r[o.id] = o.total;
return r;
});
But I need some like this:
[
{"id":"2018", "name":"test", "total":1200},
{"id":"2019", "name":"wath", "total":2300},
{"id":"2020", "name":"zooi", "total":1000},
]
How can I do it?
Upvotes: 5
Views: 8596
Reputation:
import uniqBy from 'lodash/uniqBy'
export function transform (array) {
const newArray = []
const uniq = uniqBy(array, 'id')
uniq.forEach(item => {
const total = array
.filter(({id}) => item.id === id)
.reduce((sum, current) => sum + current.total, 0)
newArray.push({
...item,
total
})
})
return newArray
}
Upvotes: -1
Reputation: 1069
You can try this:
const result = Object.values(data.reduce((r, o) => (r[o.id]
? (r[o.id].total += o.total)
: (r[o.id] = {...o}), r), {}));
Upvotes: 5
Reputation: 31682
Change your reduce
to:
let result = data.reduce(function(acc, obj) { // for each obj in data
if(acc.map.hasOwnProperty(obj.id)) { // if the map contains an object for the current object's id
acc.map[obj.id].total += +obj.total; // then add the current object's total to it
} else { // otherwise
var newObj = Object.assign({}, obj); // create a new object (a copy of the current object)
acc.map[obj.id] = newObj; // add the new object to both the map
acc.data.push(newObj); // ... and the data array
}
return acc;
}, {data: [], map: {}}).data; // the accumulator should have an array for the data objects (which will be our result) and a map object which maps the ids to the objects in the data array. Once our reduce finishes its work, we assign the data array of the accumulator to result
Example:
let data =[ {"id":"2018", "name":"test", "total":1200}, {"id":"2019", "name":"wath", "total":1500}, {"id":"2019", "name":"wath", "total":1800}, {"id":"2020", "name":"zooi", "total":1000} ];
let result = data.reduce(function(acc, obj) {
if(acc.map.hasOwnProperty(obj.id)) {
acc.map[obj.id].total += +obj.total;
} else {
var newObj = Object.assign({}, obj);
acc.map[obj.id] = newObj;
acc.data.push(newObj);
}
return acc;
}, {data: [], map: {}}).data;
console.log(result);
Upvotes: 1
Reputation: 22885
let data =[
{"id":"2018", "name":"test", "total":1200},
{"id":"2019", "name":"wath", "total":1500},
{"id":"2019", "name":"wath", "total":1800},
{"id":"2020", "name":"zooi", "total":1000},
];
let map = data.reduce((prev, next) =>{
if (next.id in prev) {
prev[next.id].total += next.total;
} else {
prev[next.id] = next;
}
return prev;
}, {});
let result = Object.keys(map).map(id => map[id]);
console.log(result);
Upvotes: 10