I have the following object:
data = [
{ name: 'foo', type: 'fizz', val: 9 },
{ name: 'foo', type: 'buzz', val: 3 },
{ name: 'bar', type: 'fizz', val: 4 },
{ name: 'bar', type: 'buzz', val: 7 },
];
And used lodash map:
result = _.map(data, function item, idx){
return {
key: item[key],
values: item.value,
}
}
Which results in:
[
{ key: foo, val: 9 },
{ key: foo, val: 3 },
{ key: bar, val: 4 },
{ key: bar, val: 7 },
]
but now I'm trying to return:
[
{ key: 'foo', val: 12 },
{ key: 'bar', val: 11 },
]
I tried using reduce which seems to only output to a single object, which I could then convert back into an array, but I feel like there must be an elegant way to use lodash to go from my source data straight to my desired result without all of the intermediate steps.
I thought this was addressing my exact problem, but it seems like quite a bit of work just to have to convert the object into the desired array of objects outlined above.
Cheers.
Interestingly not straight forward, because of wanting to accumulate the value by key, but then wanting the key as a value of the property key. So somewhat like an inverse map reduce:
var result =
_.chain(data)
.reduce(function(memo, obj) {
if(typeof memo[obj.name] === 'undefined') {
memo[obj.name] = 0;
}
memo[obj.name] += obj.val;
return memo;
}, {})
.map(function (val, key) {
return {key: key, val: val};
})
.value();
For the sake of brevity in es6:
_.chain(data)
.reduce((memo, obj) => {
memo[obj.name = obj.val] += obj.val;
return memo;
}, {})
.map((val, key) => ({key, val}))
.value();
A twist to the accepted answer that uses groupBy instead of reduce to do the initial grouping:
var result = _.chain(data)
.groupBy('name')
.map((group, key) => ({ key, val : _.sumBy(group, 'val') }))
.value();
You can get all the unique names
using map() and uniq(), and then map() each name to get their respective sums using sumBy().
var result = _(data)
.map('name')
.uniq()
.map(key => ({
key,
val: _(data).filter({ name: key }).sumBy('val')
}))
.value();
var data = [
{ name: 'foo', type: 'fizz', val: 9 },
{ name: 'foo', type: 'buzz', val: 3 },
{ name: 'bar', type: 'fizz', val: 4 },
{ name: 'bar', type: 'buzz', val: 7 }
];
var result = _(data)
.map('name')
.uniq()
.map(key => ({
key,
val: _(data).filter({ name: key }).sumBy('val')
}))
.value();
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.js"></script>
Here is a non es6 version:
var result = _(data)
.map('name')
.uniq()
.map(function(key) {
return {
key: key,
val: _(data).filter({ name: key }).sumBy('val')
};
})
.value();