Reputation: 609
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
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
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
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
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
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