0

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 :)

mplungjan
  • 169,008
  • 28
  • 173
  • 236
kcNeko
  • 587
  • 1
  • 7
  • 23
  • 2
    Show us what you've tried? – StudioTime Jan 03 '18 at 09:04
  • 1
    reduce/map ? ... – mplungjan Jan 03 '18 at 09:05
  • hash table ...? – Nina Scholz Jan 03 '18 at 09:06
  • You need to describe the merging rules more specific. As I can see, numbers are summed up. But what should happen to strings? Is it guarantied that they are the same for every object? – Larce Jan 03 '18 at 09:10
  • as shown above the strings or the `type` in every array they only have the same strings so strings will remain as it is after is simplified. – kcNeko Jan 03 '18 at 09:13
  • Possible duplicate of [Sum javascript object propertyA values with same object propertyB in array of objects](https://stackoverflow.com/questions/19233283/sum-javascript-object-propertya-values-with-same-object-propertyb-in-array-of-ob) – Rajesh Jan 03 '18 at 09:22

5 Answers5

2

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)
Rohit Agrawal
  • 1,496
  • 9
  • 20
0

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; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

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);
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
0

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; }
Hassan Imam
  • 21,956
  • 5
  • 41
  • 51
0
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.

Shanon Jackson
  • 5,873
  • 1
  • 19
  • 39