6

I have the following array:

var items = [
   {price1: 100, price2: 200, price3: 150},
   {price1: 10, price2: 50},
   {price1: 20, price2: 20, price3: 13},
]

I need to get object with sum of all keys like the following:

var result = {price1: 130, price2: 270, price3: 163};

I know I may to use just loop but I'm looking for a approach in underscore style :)

2
  • Have you tried their documentation? If so, have you tried to accomplish this for yourself? Commented Jun 27, 2013 at 18:28
  • @ArturNowak: I'll go ahead and clean up most of my comments since they no longer make sense now that the rest are gone. It was a fruitless conversation anyway. Commented Jun 27, 2013 at 20:22

3 Answers 3

5

Not very pretty, but I think the fastest method is to do it like this

_(items).reduce(function(acc, obj) {
  _(obj).each(function(value, key) { acc[key] = (acc[key] ? acc[key] : 0) + value });
  return acc;
}, {});

Or, to go really over the top (I think it will can be faster than above one, if you use lazy.js instead of underscore):

_(items).chain()
  .map(function(it) { return _(it).pairs() })
  .flatten(true)
  .groupBy("0") // groups by the first index of the nested arrays
  .map(function(v, k) { 
    return [k, _(v).reduce(function(acc, v) { return acc + v[1] }, 0)]     
  })
  .object()
  .value()
Sign up to request clarification or add additional context in comments.

6 Comments

Should use .each() or .forEach() (whatever underscore names it) instead of .map() since you're not building an Array.
@Erik: I thought you wanted "better than loop"? This uses two loops.
@Erik: I already read it. Read my first comment under your question again.
I'm looking for underscore approach. Where here is the loops like for, for/in in Artur answer?
@Erik: They're called .reduce() and .map()
|
1

For aggregating I'd recommend reduce:

_.reduce(items, function(acc, o) {
    for (var p in acc) acc[p] += o[p] || 0;
    return acc;
}, {price1:0, price2:0, price3:0});

Or better

_.reduce(items, function(acc, o) {
    for (var p in o)
        acc[p] = (p in acc ? acc[p] : 0) + o[p];
    return acc;
}, {});

4 Comments

What if items have different keys than price1, price2 and price3?
Well, this solution lets you choose which properties you want to have summed up. Of course you might also compute that list dynamically, or just use for (var p in o) acc[p] = (p in acc ? acc[p] : 0) + o[p]; instead (especially if each item has different properties)
Returns {price1: 130, price2: 270, price3: NaN}
@YD1m: Thanks for the hint, I first believed every item had the same set of properties. Solution adapted (and integrated second one)
0

Js from hell:

var names = _.chain(items).map(function(n) {  return _.keys(n);  }).flatten().unique().value();    
console.log(_.map(names, function(n) {              
      return  n + ': ' + eval((_.chain(items).pluck(n).compact().value()).join('+')); 
}).join(', '));  

jsfiddle

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.