DEV Community

Cover image for Javascript: how to merge multiple objects with sum of values
Katsiaryna (Kate) Lupachova
Katsiaryna (Kate) Lupachova

Posted on

Javascript: how to merge multiple objects with sum of values

Assume we have an array of objects - baskets with fruits.

const fruits = [
  {
    apples: 4,
    pears: 6,
    oranges: 2,
  },
  {
    bananas: 2,
    oranges: 5,
  },
  {
    pears: 8,
    apples: 3,
    bananas: 10,
  },
  {},
  {
    pears: 7,
    apples: 5,
  },
  {
    mangos: 1,
  },
];
Enter fullscreen mode Exit fullscreen mode

There are different types of fruits with different quantities in each basket (one basket even empty).

How can we merge all these objects (baskets) into one and count total sum of each fruit?

Let’s create helper method.

const mergeFruits = data => {
  const result = {}; //(1)

  data.forEach(basket => { //(2)
    for (let [key, value] of Object.entries(basket)) { //(3)
      if (result[key]) { //(4)
        result[key] += value; //(5)
      } else { //(6)
        result[key] = value;
      }
    }
  });
  return result; //(7)
};
Enter fullscreen mode Exit fullscreen mode
  1. Result object, empty.
  2. Loop through an array of objects using Array.prototype.forEach() method.
  3. Iterate over each object's (basket's) key-value pairs using Object.entries() method.
  4. Check if the result object has a property with the name of the key.
  5. If yes (true), add to the previous value of the property the value of the key, e.g. if there is a property “apples” with value “4” in the result object, then add more apples from the next basket.
  6. If no (false), then it’s a new property (a new fruit) for a result object, so create this property and assign the corresponding value to it.
  7. Return merged object

If we run the code and print the result into console:

const mergedObject = mergeFruits(fruits);

console.log(mergedObject);
Enter fullscreen mode Exit fullscreen mode

we’ll get the following output:

{ apples: 12, pears: 21, oranges: 7, bananas: 12, mangos: 1 }
Enter fullscreen mode Exit fullscreen mode

All objects (baskets) in the array merged into one with the sum of each property’s (fruit) value.

Originally posted on my own blog

Discussion (8)

Collapse
aleksandrhovhannisyan profile image
Aleksandr Hovhannisyan • Edited on

No need to reinvent the wheel; you can just use Array.reduce:

const basket = fruits.reduce((basket, fruit) => {
    for (const [fruitName, fruitCount] of Object.entries(fruit)) {
        if (!basket[fruitName]) {
            basket[fruitName] = 0;
        }

        basket[fruitName] += fruitCount;
    }

    return basket;
}, {});
Enter fullscreen mode Exit fullscreen mode

What you did is the same thing, but without taking advantage of reduce.

Collapse
ramonak profile image
Katsiaryna (Kate) Lupachova Author

Good point! Thanks!
But I think it's good to have different solutions of the same problem;)

Collapse
aleksandrhovhannisyan profile image
Aleksandr Hovhannisyan

Definitely! Your solution demonstrates how Array.reduce would work under the hood for this problem, so it's no "bad" per se.

Thread Thread
patarapolw profile image
Pacharapol Withayasakpunt

I think Array.reduce is more like recursive function, rather than taking advantage of mutability.

Thread Thread
timhlm profile image
moth

This is right on the money. There’re certain times when mutating things makes sense, and others when generating a new array with reduce is a better choice. It’s all about knowing when to use the right tool.

Collapse
oakleyarts profile image
John Galantini

This is exactly the solution I was looking for, and Aleksandr's response is great too.

Thank you to both of you!

Collapse
ramonak profile image
Katsiaryna (Kate) Lupachova Author

Thank you!

Collapse
trongphamitr profile image
trongpham-itr

I use lodash library

const _ = require('lodash');
const fruits = [];
_.reduce(fruits, (prev, curr) => _.mergeWith(prev, curr, _.add))
Enter fullscreen mode Exit fullscreen mode