Reputation: 603
I have this multidimensional array and I need to merge the fields that are equal and sum the sum values
var data = [
[
{field: 123, sum: 100},
{field: 345, sum: 98}
],[
{field: 123, sum: 12},
{field: 345, sum: 20}
]
];
So from this array I need a new one like this.
var newArray = [
{field: 123, sum: 112},
{field: 345, sum: 118}
];
and here is my code.
var newArray = [];
for(var i = 0; i < data.length; i++) {
for(var j = 0; j < data[i].length; j++) {
var matched = false;
for(var c = 0; c < newArray.length; c++) {
if(data[i][j].field == newArray[c].field) {
matched = true;
newArray[c].sum + data[i][j].sum;
}
}
console.log(data[i][j]);
if(!matched) {
newArray.push(data[i][j]);
}
}
}
but I don't get the values right. console.log(newArray);
Upvotes: 1
Views: 4397
Reputation: 1761
In functional programming, this would be a classic map-reduce problem, or more specifically a reduce-by-key.
If you are working with underscore, you could do something like this:
var op = _.chain(data)
//first put it all in one array
.flatten()
//then group by the field
.groupBy(function(item){return item.field;})
//then sum up all of the "sum" properties
.mapObject(function(val,key){
return _.reduce(val, function(total,sum){
return total + sum.sum;
},0);
})
//then map it back into our original data structure
.pairs()
.map(function(item){
return {field: item[0], sum: item[1]};
});
Upvotes: 2
Reputation: 191749
ECMAScript6 solution (if available):
data
.reduce((a, b) => a.concat(b))
.reduce((a, b) => {
var idx = a.findIndex(elem => elem.field == b.field);
if (~idx) {
a[idx].sum += b.sum;
}
else {
a.push(JSON.parse(JSON.stringify(b)));
}
return a;
}, []);
Your issue is just a typo, though:
- newArray[c].sum + data[i][j].sum
+ newArray[c].sum += data[i][j].sum
Upvotes: 1
Reputation: 1687
just have a look at this code
<script>
var data = [
[
{field: 123, sum: 100},
{field: 345, sum: 98}
],[
{field: 123, sum: 12},
{field: 345, sum: 20}
]
];
var o=[];
var j=0;
while(j<data.length)
{
var obj1={};
var field; sum=0;
for(i=0; i<data.length; i++)
{
field=data[i][j].field;
sum=sum+data[i][j].sum;
}
obj1.field=field;
obj1.sum=sum;
o.push(obj1);
j++;
}
console.log(o)
</script>
Upvotes: 0
Reputation: 1261
Your problem is in the line
newArray[c].sum + data[i][j].sum;
This line performs the calculation, but it is not stored in newArray. If you change the operator to += your function will work correctly.
newArray[c].sum + data[i][j].sum; // Sums the two values
newArray[c].sum += data[i][j].sum; // Sums and saves them to newArray[c].sum
A correct solution is shown here in this jsFiddle.
var newArray = [];
for(var i = 0; i < data.length; i++){
var objects = data[i];
for(var n = 0; n < objects.length; n++){
var existed = false;
for(var z = 0; z < newArray.length; z++){
if(newArray[z].field === objects[n].field){
newArray[z].sum += objects[n].sum;
existed = true;
}
}
if(!existed){
newArray.push({field : objects[n].field, sum: objects[n].sum});
}
}
}
You cycle through all the elements, and then sum them in a new array called newArray. It looks if an object with the field already exists, and if it does, adds the sum to the existing element. If not, it creates a new element with the field value and the initial sum.
Upvotes: 0