Javascript中的多维数组累积和

时间:2016-03-24 02:42:52

标签: javascript multidimensional-array cumulative-sum

给定一个多维数组:

var a = [[3,2,5], [4,1,7], [1,6,8]];

我想对每个数组进行累加求和以返回以下结果:

[[3,2,5], [7,3,12], [8,9,20]];
  • 每个子阵列的第一个元素的总和:3 4 1
  • 每个子阵列的第二个元素的总和:2 1 6
  • 每个子阵列的第3个元素的总和:5 7 8

我尝试过使用reduce(),但无法获得预期效果。

任何建议,非常感谢。

取值

更新 - 把它提升到一个新的水平:

var a = [
    [new Date(), 3,2,5], 
    [new Date(), null,1,7], 
    [new Date(), null,6,8], 
    [new Date(), 1,2,3]
];

应该导致:

[[new Date(), 3,2,5], 
 [new Date(), null,3,12],
 [new Date(), null,9,20],
 [new Date(), 4,11,23]]

我的方法是创建一个多维的offsetIndex数组:

var offsetIdx = [];
        for (var i=1; i<a.length; i++) {

            for (var z=0; z<a[i].length; z++) {
                var zValue = a[i][z];

                oIdx = offsetIdx[z] || 0;

                a[i][z] = zValue && z!==0 ? a[i-1-oIdx][z] + zValue : zValue;

                if(!zValue){
                    offsetIdx[z] = oIdx + 1;
                } else {
                    offsetIdx[z] = 0; 
                }
            }
        }

很高兴看到其他方法和方法使它超轻。

5 个答案:

答案 0 :(得分:3)

for (var i=1; i<a.length; i++) {
  for (var z=0; z<a[i].length; z++) {
   a[i][z] = a[i-1]][z] + a[i][z]
  }
}

应该在循环运行时动态更新数组。 这是破坏性的,因此它将修改原始数组。

答案 1 :(得分:3)

  function cumulativeSum(arr) {
    var result = [arr[0]];
    for(var i = 1; i < arr.length; i++) {
        result.push([]);
        for(var j = 0; j < arr[0].length; j++) {
          result[i].push(result[i - 1][j] + arr[i][j]);
        }
    }
    return result;
}
    
document.body.innerHTML = JSON.stringify(cumulativeSum(
  [[3,2,5], [4,1,7], [1,6,8]]
))

与其他答案不同,这个答案不具有破坏性,保留原始数组并返回结果。

答案 2 :(得分:1)

使用Array.reduce,它看起来像这样

var arr  = [[3,2,5], [4,1,7], [1,6,8]];

var arr2 = arr.reduce(function(a,b) {
    var nested = Array.isArray(a[0]);
    b = b.map(function(x,i) {
    	return x + (nested ? a[a.length-1] : a)[i];
    });
    if ( nested ) a.push(b);
    return nested ? a : [a,b];
});

document.body.innerHTML = '<pre>' + JSON.stringify(arr2, 0, 4) + '</pre>';

这是一个轻微的“优化”(高尔夫)版本,传递了减少和切割数组的起点

var arr  = [[3,2,5], [4,1,7], [1,6,8]];

var arr2 = arr.slice(1).reduce(function(a,b) {
	return [a.push(b.map(function(x,i) {return x+a[a.length-1][i]})), a].pop();
},[arr[0]]);

document.body.innerHTML = '<pre>' + JSON.stringify(arr2, 0, 4) + '</pre>';

使用ES2015使其成为单行

var arr  = [[3,2,5], [4,1,7], [1,6,8]];
var a2 = arr.slice(1).reduce((a,b)=>[a,a.push(b.map((x,i)=>x+a[a.length-1][i]))][0],[arr[0]]);

document.body.innerHTML = '<pre>' + JSON.stringify(a2, 0, 4) + '</pre>';

答案 3 :(得分:0)

这将为您提供所有元素的总和。不是你问的问题,但我会在这里留下这个答案,以供将来访问问题标题的访客使用。

  1. Flatten first using your favorite library(下划线和lodash都有)
  2. 然后减少+总和。

    _.flatten([1, [2, [3, [4]], 5]]);
    // → [1, 2, [3, [4]], 5]
    

答案 4 :(得分:0)

多么糟糕的问题。

为什么不首先转置数组?关于这个问题的答案 - Transposing a 2D-array in JavaScript - 建议underscore.js解决方案:

_.zip.apply(_, [[1,2,3], [1,2,3], [1,2,3]])

这样做。有很多方法。

然后总和应该更容易 - 仅.map(f)其中f是你在一个数组函数上的总和。

IMO这是一个很好的,可读的解决方案,因为“转置+求和”非常适用于问题的列和性质,我会避免使用命令式或循环重的解决方案来掩盖这一点。