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

6
  • 2
    Show us what you've tried? Commented Jan 3, 2018 at 9:04
  • 1
    reduce/map ? ... Commented Jan 3, 2018 at 9:05
  • hash table ...? Commented Jan 3, 2018 at 9: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? Commented Jan 3, 2018 at 9: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. Commented Jan 3, 2018 at 9:13

5 Answers 5

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)

Sign up to request clarification or add additional context in comments.

2 Comments

what do you do for other month's?
Hi @NinaScholz, updated my answer for variable months.
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; }

1 Comment

Please choose to close such question as duplicate instead.
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);

Comments

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; }

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.