diegoddox
diegoddox

Reputation: 603

javascript sum multidimensional array

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

Answers (4)

Chris Scott
Chris Scott

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

Explosion Pills
Explosion Pills

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

shreyansh
shreyansh

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

Robin
Robin

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

Related Questions