Javascript merge 2 arrays and sum same key values

2019-04-10 22:39发布

问题:

I have 2 array:

    var array1 = [[5,10],[6,10],[7,10],[8,10],[9,10]];
    var array2 = [[1,10],[2,10],[3,10],[4,10],[5,40],[6,40]];

Want to get 1 merged array with the sum of corresponding keys;

    var array1 = [[1,10],[2,10],[3,10],[4,10],[5,50],[6,50],[7,10],[8,10],[9,10]];

Both arrays have unique keys, but the corresponding keys needs to be summed.

I tried loops, concat, etc but can't get the result i need.

anybody done this before?

回答1:

This is one way to do it:

var sums = {}; // will keep a map of number => sum

// for each input array (insert as many as you like)
[array1, array2].forEach(function(array) {
    //for each pair in that array
    array.forEach(function(pair) {
        // increase the appropriate sum
        sums[pair[0]] = pair[1] + (sums[pair[0]] || 0);
    });
});

// now transform the object sums back into an array of pairs
var results = [];
for(var key in sums) {
    results.push([key, sums[key]]);
}

See it in action.



回答2:

You can use .reduce() to pass along an object that tracks the found sets, and does the addition.

DEMO: http://jsfiddle.net/aUXLV/

var array1 = [[5,10],[6,10],[7,10],[8,10],[9,10]];
var array2 = [[1,10],[2,10],[3,10],[4,10],[5,40],[6,40]];

var result =
    array1.concat(array2)
          .reduce(function(ob, ar) {
              if (!(ar[0] in ob.nums)) {
                  ob.nums[ar[0]] = ar
                  ob.result.push(ar)
              } else
                  ob.nums[ar[0]][1] += ar[1]

              return ob
          }, {nums:{}, result:[]}).result

If you need the result to be sorted, then add this to the end:

.sort(function(a,b) {
    return a[0] - b[0];
})


回答3:

a short routine can be coded using [].map()

var array1 = [[5,10],[6,10],[7,10],[8,10],[9,10]];
var array2 = [[1,10],[2,10],[3,10],[4,10],[5,40],[6,40]];

array1=array2.concat(array1).map(function(a){
  var v=this[a[0]]=this[a[0]]||[a[0]];
  v[1]=(v[1]||0)+a[1];
 return this;
},[])[0].slice(1);

alert(JSON.stringify(array1)); 
//shows: [[1,10],[2,10],[3,10],[4,10],[5,50],[6,50],[7,10],[8,10],[9,10]]

i like how it's just 3 line of code, doesn't need any internal function calls like push() or sort() or even an if() statement.



回答4:

Try this:

var array1 = [[5,10],[6,10],[7,10],[8,10],[9,10]];
var array2 = [[1,10],[2,10],[3,10],[4,10],[5,40],[6,40]];
var res = [];

someReasonableName(array1, res);
someReasonableName(array2, res);

function someReasonableName(arr, res) {
  var arrLen = arr.length
  , i = 0
  ;

  for(i; i < arrLen; i++) {
    var ar = arr[i]
    , index = ar[0]
    , value = ar[1]

    ;

    if(!res[index]) {
        res[index] = [index, 0];
    }
    res[index][1] += value;
  }
}

console.log(JSON.stringify(res, null, 2));

So, the result may have holes. Just like 0th index. Use the below function if you want to ensure there are no holes.

function compact(arr) {
  var i = 0
  , arrLen = arr.length
  , res = []
  ;
  for(i; i < arrLen; i++) {
    var v = arr[i]
    ;
    if(v) {
      res[res.length] = v;
    }
  }
  return res;

}

So, you can do:

var holesRemoved = compact(res);

And finally if you don't want the 0th elem of res. Do res.shift();

Disclaimer: I am not good with giving reasonable names.