for array like this
[{ dep: 'A', qt: 10, price: 5},
{ dep: 'A', qt: 5, price: 2.30 },
{ dep: 'B', qt: 3, price: 2.20 },
{ dep: 'C', qt: 1, price: 4 },
{ dep: 'C', qt: 4, price: 10 }
...etc..
]
What's the elegant way to both group and sum values, resulting into:
[{ dep: 'A', qt: 15, price: 61.5 },
{ dep: 'B', qt: 3, price: 2.20 },
{ dep: 'C', qt: 5: price: 44 }
]
for array like this
[{ dep: 'A', qt: 10, price: 5},
{ dep: 'A', qt: 5, price: 2.30 },
{ dep: 'B', qt: 3, price: 2.20 },
{ dep: 'C', qt: 1, price: 4 },
{ dep: 'C', qt: 4, price: 10 }
...etc..
]
What's the elegant way to both group and sum values, resulting into:
[{ dep: 'A', qt: 15, price: 61.5 },
{ dep: 'B', qt: 3, price: 2.20 },
{ dep: 'C', qt: 5: price: 44 }
]
Share
Improve this question
edited Apr 12, 2014 at 2:06
mu is too short
435k71 gold badges858 silver badges818 bronze badges
asked Apr 12, 2014 at 0:25
iLemmingiLemming
36.3k61 gold badges198 silver badges316 bronze badges
3 Answers
Reset to default 8You could do something like this:
function sumInvoices(p, c) {
return _.extend(p, {qt:p.qt + c.qt, price:p.price + c.qt*c.price});
};
var b = _(a)
.groupBy('dep')
.map(function(b) {return b.reduce(sumInvoices, {dep:b[0].dep, qt:0, price:0})})
.valueOf();
I'd probably go straight to Array.prototype.reduce
for something like this:
var b = a.reduce(function(cache, e) {
var sum = cache.by_dep[e.dep];
if(!sum) {
sum = cache.by_dep[e.dep]
= { dep: e.dep, qt: 0, price: 0 };
cache.a.push(sum);
}
sum.qt += e.qt;
sum.price += e.price;
return cache;
}, { by_dep: { }, a: [ ] }).a;
You want easy access by dep
so you index your running totals by dep
(by_dep: { }
) but you also want an array at the end so store the same references in an array (a: [ ]
). Then pull out the a
cache at the end and you're done.
Demo: http://jsfiddle/ambiguous/T8jgx/
That's probably just as simple as a pipeline of Underscore/Lodash calls. But if you must use those libraries then you could _(a).reduce(...)
instead of a.reduce(...)
.
2021's answer
You can use Array#reduce
with the highest performance O(n)
time plexity in this way:
const arr = [{ dep: 'A', qt: 10, price: 5},{ dep: 'A', qt: 5, price: 2.30 },{ dep: 'B', qt: 3, price: 2.20 },{ dep: 'C', qt: 1, price: 4 },{ dep: 'C', qt: 4, price: 10 }];
const result = arr.reduce((acc, {dep, qt, price}) => {
acc[dep] ??= {dep, qt: 0, price: 0};
acc[dep]["qt"]+= qt;
acc[dep]["price"]+= (price * qt);
return acc;
}, {});
console.log(Object.values(result));