kcNeko
kcNeko

Reputation: 609

Javascript: Merging 2 or more Objects in the Same Array

Any idea how to restructure a data structure like this

var data = [
  [{
    jan: 10,
    feb: 20,
    mar: 30,
    type: "one"
  },
  {
    jan: 20,
    feb: 10,
    mar: 40,
    type: "one"
  }],
  [
    {
    jan: 10,
    feb: 20,
    mar: 30,
    type: "two"
  },
  {
    jan: 20,
    feb: 10,
    mar: 40,
    type: "two"
  }]
]

console.log(data)

into something like this?

var data = [
  {
    jan: 30,
    feb: 30,
    mar: 70,
    type: "one"
  },
    {
    jan: 30,
    feb: 30,
    mar: 70,
    type: "two"
  }
]

console.log(data)

As seen in the example, objects in the same array are merged and the jan , feb and mar keys are added.

I'm at the end of my wits. Thanks in advance :)

Upvotes: 0

Views: 124

Answers (5)

Shanon Jackson
Shanon Jackson

Reputation: 6581

data.reduce((a,c) => {
    return a.concat(c.reduce((a2,c2) => {
        if(Object.keys(a2).length === 0) return c2;
        return Object.assign({}, a2, {jan: a2.jan + c2.jan, feb: a2.feb + c2.feb, mar: a2.mar + c2.mar})
    },{}))
},[])

Nested reduce fully immutable solution.

Upvotes: 0

Hassan Imam
Hassan Imam

Reputation: 22574

You can use array#reduce to group your data based on the type value. Use array#forEach to iterate through each array.

var data = [ [{ jan: 10, feb: 20, mar: 30, type: "one" }, { jan: 20, feb: 10, mar: 40, type: "one" }], [ { jan: 10, feb: 20, mar: 30, type: "two" }, { jan: 20, feb: 10, mar: 40, type: "two" }] ];
var result = Object.values(data.reduce((r,a) => {
  a.forEach(o => {
    r[o.type] = r[o.type] || Object.assign({'type': o.type});
    Object.keys(o).forEach(k => {
      if(k !== 'type')
        r[o.type][k] = (r[o.type][k] || 0) + o[k];
    });
  });
  return r;
},{}));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 0

gurvinder372
gurvinder372

Reputation: 68443

Use reduce and forEach

var output = Object.values( data.reduce( function( a, c ){
  c.forEach( function( item ){
     a[ item.type ] = a[ item.type ] || { jan: 0, feb: 0, mar: 0, type: item.type };
     a[ item.type ].jan += item.jan; 
     a[ item.type ].feb += item.feb;
     a[ item.type ].mar += item.mar;
  });
  return a;
}, {}));

Demo

var data = [
  [{
    jan: 10,
    feb: 20,
    mar: 30,
    type: "one"
  },
  {
    jan: 20,
    feb: 10,
    mar: 40,
    type: "one"
  }],
  [
    {
    jan: 10,
    feb: 20,
    mar: 30,
    type: "two"
  },
  {
    jan: 20,
    feb: 10,
    mar: 40,
    type: "two"
  }]
];

var output = Object.values( data.reduce( function( a, c ){
  c.forEach( function( item ){
     a[ item.type ] = a[ item.type ] || { jan: 0, feb: 0, mar: 0, type: item.type };
     a[ item.type ].jan += item.jan;
     a[ item.type ].feb += item.feb;
     a[ item.type ].mar += item.mar;
  });
  return a;
}, {}));

console.log(output);

Upvotes: 0

Rohit Agrawal
Rohit Agrawal

Reputation: 1521

You can use map and reduce functions on javascript arrays to achieve your result.

Use map to iterate over the sub arrays inside your main array and use reduce inside those sub arrays to sum up the months data.

var data = [
  [{
    jan: 10,
    feb: 20,
    mar: 30,
    type: "one"
  },
  {
    jan: 20,
    feb: 10,
    mar: 40,
    type: "one"
  }],
  [
    {
    jan: 10,
    feb: 20,
    mar: 30,
    type: "two"
  },
  {
    jan: 20,
    feb: 10,
    mar: 40,
    type: "two"
  }]
]

var newData = data.map(function(arr){
  return arr.reduce(function(acc, ele, i){
    if(i === 0){
      acc = ele;
    }
    else{
      var keys= Object.keys(ele);
      keys.splice(keys.indexOf("type"), 1);
      keys.forEach(function(key){
         acc[key] += ele[key];
      })
    }
    return acc;
  },{});
});
console.log(newData)

Upvotes: 2

Nina Scholz
Nina Scholz

Reputation: 386883

You could take a hash table for the object with the same type and add all values of properties which are not type.

var data = [[{ jan: 10, feb: 20, mar: 30, type: "one" }, { jan: 20, feb: 10, mar: 40, type: "one" }], [{ jan: 10, feb: 20, mar: 30, type: "two" }, { jan: 20, feb: 10, mar: 40, type: "two" }]],
    hash = Object.create(null),
    grouped = [];

data.forEach(function (a) {
    a.forEach(function (o) {
        if (!hash[o.type]) {
            hash[o.type] = { type: o.type };
            grouped.push(hash[o.type]);
        }
        Object.keys(o).forEach(function (k) {
            if (k === 'type') {
                return;
            }
            hash[o.type][k] = (hash[o.type][k] || 0) + o[k];
        });
    });
});

console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 0

Related Questions