Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to merge two objects and sum the values of same key?

I have two objects similar to this:

let data = [[
  {
    10: {key1: 1, key2: 2, key3: 3},
    11: {key1: 1, key2: 2, key3: 3},
    12: {key1: 1, key2: 2, key3: 3},
    },
  {},
  {}
],
[
  {
    10: {key1: 1, key2: 2, key3: 3},
    11: {key1: 1, key2: 2, key3: 3},
    12: {key1: 1, key2: 2, key3: 3},
    },
  {},
  {}
]]

I wanna create a new object and sum every value of each key. Like this:

let newData = [
      {
        10: {key1: 2, key2: 4, key3: 6},
        11: {key1: 2, key2: 4, key3: 6},
        12: {key1: 2, key2: 4, key3: 6},
        },
      {},
      {}
    ]

Each object has three object in them. In these three objects, there is 45 keys, each of them has a object with three keys/values.

I can't find any good solution to sum every value.

My current solution is that I first loop thru data:

let count = 0;
let count2 = 0;
for(let ob of data){
     for(let child in ob[0]){
          keyOne = ob[0][child].keyOne;
          keyTwo = ob[0][child].keyTwo;
          keyThree = ob[0][child].keyThree;
          keyFour = ob[0][child].keyFour;
          if(count < 45) {
               newData[0][count].keyOne += keyOne;
               newData[0][count].keyTwo += gkeyTwop;
               newData[0][count].keyThree += keyThree;
               newData[0][count].keyFour += keyFour;
          } else {
               newData[0][count2].keyOne += keyOne;
               newData[0][count2].keyTwo += keyTwo;
               newData[0][count2].keyThree += keyThree;
               newData[0][count2].keyFour += keyFour;
               count2++;

          }
          count++;
     }

In the worst case, data got three objects with 45 keys each. Then I must do this three times. This seems really bad. There must be a better way. Tips?

like image 297
mintermasher Avatar asked Apr 03 '17 11:04

mintermasher


People also ask

How do you sum multiple objects with the same key in an array?

First iterate through the array and push the 'name' into another object's property. If the property exists add the 'value' to the value of the property otherwise initialize the property to the 'value'. Once you build this object, iterate through the properties and push them to another array. Hope this helps.

How do you combine two objects with the same properties?

To merge objects into a new one that has all properties of the merged objects, you have two options: Use a spread operator ( ... ) Use the Object. assign() method.

Which function can be used to merge key value pairs from source object to a target object?

assign() method. The “Object. assign()” method is used to clone the enumerable “key-value” pair of an already created source object into the target object.


2 Answers

Here is solution with reduce() and few forEach() loops because you need to loop nested objects also.

var data = [[{"10":{"key1":1,"key2":2,"key3":3},"11":{"key1":1,"key2":2,"key3":3},"12":{"key1":1,"key2":2,"key3":3}},{},{}],[{"10":{"key1":1,"key2":2,"key3":3},"11":{"key1":1,"key2":2,"key3":3},"12":{"key1":1,"key2":2,"key3":3}},{},{}]]

var result = data.reduce(function(r, e, i) {
  if (i == 0) r = r.concat(e)
  else  {
  e.forEach(function(a, j) {
       Object.keys(a).forEach(function(key) {
          if (!r[j][key]) r[j][key] = a[key]
          else {
            Object.keys(a[key]).forEach(function(k) {
              r[j][key][k] += a[key][k]
            })
          }
      })
    })
  }
  return r;
}, [])

console.log(result)
like image 179
Nenad Vracar Avatar answered Oct 19 '22 05:10

Nenad Vracar


You could use Array#reduce and map the values of the inner array after adding the values.

var data = [[{ 10: { key1: 1, key2: 2, key3: 3 }, 11: { key1: 1, key2: 2, key3: 3 }, 12: { key1: 1, key2: 2, key3: 3 }, }, {}, {}], [{ 10: { key1: 1, key2: 2, key3: 3 }, 11: { key1: 1, key2: 2, key3: 3 }, 12: { key1: 1, key2: 2, key3: 3 }, }, {}, {}]],
    result = data.reduce((a, b) => 
        a.map((v, i) =>
            (Object.keys(b[i]).forEach(k =>
                Object.keys(b[i][k]).forEach(l => 
                    v[k][l] = (v[k][l] || 0) + b[i][k][l]))
            , v)
        )
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
like image 20
Nina Scholz Avatar answered Oct 19 '22 06:10

Nina Scholz