1

Similar to this question asked previously, is there an easy way to sum two objects, or an array of objects, by key in Lodash?

{ a:12, b:8, c:17 }

and

{ a:2, b:3, c:1 }

should give

{ a:14, b:11, c:18 }
Allen Wang
  • 2,426
  • 2
  • 24
  • 48

2 Answers2

6

You can use lodash's _.mergeWith():

var o1 = { a:12, b:8, c:17 };
var o2 = { a:2, b:3, c:1 };

var result = _.mergeWith({}, o1, o2, function(objValue, srcValue) {
  return _.isNumber(objValue) ? objValue + srcValue : srcValue; 
});

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>

If you know that all values are numbers, or you always want to add values together, you can use _.add() as the merging customizer:

var o1 = { a:12, b:8, c:17, d: 'a' };
var o2 = { a:2, b:3, c:1, d: 'b' };

var result = _.mergeWith({}, o1, o2, _.add);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>

To merge an array of objects use spread syntax with _.mergeWith():

var arr = [{ a:12, b:8, c:17 }, { a:2, b:3, c:1 }];

var result = _.mergeWith({}, ...arr, function(objValue, srcValue) {
  return _.isNumber(objValue) ? objValue + srcValue : srcValue; 
});

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>

Or with Array.reduce():

var arr = [{ a:12, b:8, c:17 }, { a:2, b:3, c:1 }];

var result = arr.reduce(function(r, o) {
  return  _.mergeWith(r, o, function(objValue, srcValue) {
    return _.isNumber(objValue) ? objValue + srcValue : srcValue; 
  });
}, {});

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
  • I was trying to use reduce instead of spread, thanks for the help. – Allen Wang Mar 12 '18 at 18:19
  • 1
    Welcome. I've added an example with reduce instead of spread. – Ori Drori Mar 12 '18 at 19:21
  • In the first example, couldn't you use `_.add` as the iteratee? `_.mergeWith({}, o1, o2, _.add)` -- this is concise and to-the-point. I think the `_.isNumber()` check is redundant; `_.add` is going to type-check anyway and works fine if either argument is `undefined`. – cdhowie Apr 29 '18 at 22:53
  • You can use `_.add()` (I've add another example with it). However, use carefully because `_.add()` tries to sum everything, and it might cause weird results (the letter 'a' + null -> 'anull'). – Ori Drori Apr 30 '18 at 04:28
1

One solution is to use assignWith and add

var o1 = { a:12, b:8, c:17 };
var o2 = { a:2, b:3, c:1 };

const combined = _.assignWith({}, o1, o2, _.add)

console.log(combined);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.20/lodash.min.js"></script>
Kentin
  • 19
  • 4