简体   繁体   English

Javascript:按键求和多个数组的最有效方法

[英]Javascript: Most Efficient Way of Summing Multiple Arrays by Key

I have a JSON object returned from a web service, which is an array of objects. 我有一个从Web服务返回的JSON对象,它是一个对象数组。 I need to add the "data" arrays together to form a summed array. 我需要将“数据”数组加在一起以形成一个求和数组。 The JSON response looks like this: JSON响应如下所示:

[  
  {  
    "data":[  
       0,3,8,2,5
    ],
    "someKey":"someValue"
  },
  {  
    "data":[  
       3,13,1,0,5
    ],
    "someKey":"someOtherValue"
  }
]

There could be N amount of objects in the array. 数组中可能有N个对象。 The desired output for the above example would be: 上面示例的期望输出为:

[3, 16, 9, 2, 10]

I was intending on creating an empty array variable (var arr), then looping over the objects, and for each object, loop through the "data" key and for each key increment the corresponding key in arr by the value. 我打算创建一个空的数组变量(var arr),然后遍历对象,对于每个对象,遍历“数据”键,对于每个键,将arr中的对应键增加一个值。

Is there a more efficient way of doing this using some sort of merge function? 使用某种合并功能是否有更有效的方法?

How about this, I believe it should work for all cases. 怎么样,我相信它应该适用于所有情况。

 var data = [{ "data": [ 0, 3, 8, 2, 5 ], "someKey": "someValue" }, { "data": [ 3, 13, 1, 0, 5 ], "someKey": "someOtherValue" }]; var datas = data.reduce(function(a, b) { b.data.forEach(function(x, i) { a[i] = a[i] || 0; a[i] += x; }); return a; }, []); console.log(datas); 

If every object has the same data length, you can try with: 如果每个对象的data长度都相同,则可以尝试:

var input; // Your input data
var output = [];
for (var i = 0; i < input[0].data.length; i++) {
  output[i] = input.reduce(function(prev, item) {
    return +(item.data[i]) + prev;
  }, 0);
}

console.log(output);
// [3, 16, 9, 2, 10]

If every object has different data size: 如果每个对象的data大小都不同:

var input; // Your input data
var i = 0, output = [];
while (true) {
  var outOfIndex = true;

  var sum = input.reduce(function(prev, item) {
    if (item.data[i] !== undefined) {
      outOfIndex = false;
    }
    return +(item.data[i]) + prev;
  }, 0);

  if (outOfIndex) {
    break;
  }
  output[i++] = sum;
}

console.log(output);
// [3, 16, 9, 2, 10]

Slightly less imperative solution: 不太必要的解决方案:

//zip takes two arrays and combines them per the fn argument
function zip(left, right, fn) {
   var shorter = (right.length > left.length) ? left : right;
   return shorter.map(function(value, i) {
       return fn(left[i], right[i]);
   });
}

//assuming arr is your array of objects. Because were using
//zip, map, and reduce, it doesn't matter if the length of the
//data array changes
var sums = arr
    .map(function(obj) { return obj.data; })
    .reduce(function(accum, array) {

        //here we want to combine the running totals w/the current data
        return zip(accum, array, function(l, r) { return l + r; });
    });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM