Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javascript several corresponding array reducing/sumup

Tags:

javascript

What is the cleanest way to reduce those array ?

data = {
    id: [1, 1, 1, 3, 3, 4, 5, 5, 5, ...]
    v: [10,10,10, 5, 10 ...]
}

For each id there is a v corresponding. What I want is sum up v for each id. In this example the result should be

data = {
    id: [1, 3, 4, 5, ...]
    v: [30, 15, ...]
}
like image 815
François Richard Avatar asked Dec 28 '15 13:12

François Richard


5 Answers

I would go for the Array.prototype.reduce() ,simple and elegant solution

var ids = [1, 1, 1, 3, 3, 3, 3, 4, 5, 6, 6, 6],
  v = [10, 10, 10, 5, 10, 10, 10, 404, 505, 600, 60, 6],
  data = {};
data.v = [];
data.ids = ids.reduce(function(a, b, index) {
  if (a.indexOf(b) < 0) a.push(b);
  if (!data.v[a.indexOf(b)]) data.v[a.indexOf(b)] = 0;
  data.v[a.indexOf(b)] += v[index];
  return a;
}, []);

https://jsfiddle.net/2ssbngLr/

like image 154
vorillaz Avatar answered Nov 05 '22 22:11

vorillaz


One way of doing this, given two arrays of equal length would be to map/reduce them:

const ids = [1, 1, 1, 3, 3];
const vs = [10,10,10,5,10];

const reduced = ids
.map((val, i) => ({ id: val, value: vs[i] }))
.reduce((agg, next) => {
    agg[next.id] = (agg[next.id] || 0) + next.value;
    return agg;
}, {});

console.log(reduced);

// Object {1: 30, 3: 15}

Working example: https://jsfiddle.net/h1o5rker/1/

like image 25
Jamie Dixon Avatar answered Nov 05 '22 21:11

Jamie Dixon


I think it can be accomplished with reduce

 var data = {
   id: [1, 1, 1, 3, 3],
   v: [10, 10, 10, 5, 10]
 }

 var sumsObjs = data.v.reduce(function(sum, val, index) {
   var id = data.id[index];
   if (sum[id] !== undefined) {
     sum[id] = sum[id] + val;
   } else {
     sum[id] = val;
   }
   return sum;
 }, {});

 console.log(sumsObjs);
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>
like image 2
Bek Avatar answered Nov 05 '22 21:11

Bek


var data={
  id: [1,1,1,10,123,4531],
  v:[123,123,53,223,11,11,11]
},
 _v = data.v, vinit;

document.write(data.v+'<br>');
 for(var i=0;i<_v.length;i++){
  vinit = _v[i];
  for(var j=i+1; j<=_v.length;j++){
    if(_v[j]===vinit){
     delete _v[j];
    }
  }
 };

document.write(data.v);
var data={
  id: [1,1,1,10,123,4531],
  v:[123,123,53,223,11,11,11,...]
},
 _v = data.v, vinit;
 for(var i=0;i<_v.length;i++){
  vinit = _v[i];
  for(var j=i+1; j<=_v.length;j++){
    if(_v[j]===vinit){
     delete _v[j];
    }
  }
 }

the above code is just for the v but you can simultaneously reduce the repeating elements for id too by introducing some more variables

in the snippet you can see that there are the extra commas in the second line which shows that those elements were deleted

like image 1
anni saini Avatar answered Nov 05 '22 22:11

anni saini


If the ids are always in order, a simple for loop can solve it. There is no need to get overly complicated.

data = {
  id: [1, 1, 1, 3, 3, 4, 5, 5, 5],
  v: [10, 10, 10, 5, 10, 1, 2, 3, 4]
};

var result = {
  id: [],
  v: []
};

(function() {
  var ids = data.id,
    vals = data.v,
    lastId = ids[0],
    runningTotal = vals[0];
  for (var i = 1; i < ids.length; i++) {

    if (lastId === ids[i]) {
        runningTotal += vals[i];
    }

    if (lastId !== ids[i] || i + 1 === ids.length) {
      result.id.push(lastId);
      result.v.push(runningTotal);
      lastId = ids[i];
      runningTotal = vals[i];
    }
  }

}());

console.log(result);
like image 1
epascarello Avatar answered Nov 05 '22 21:11

epascarello