2016-03-24 66 views
2

给定一个多维数组:的多维数组累积和在Javascript

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
  • 兼总和每个子阵列的第三个元素: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; 
       } 
      } 
     } 

很高兴看到使其超轻量级的其他方法和途径。

+0

它是如何,您的输出阵列可以具有相同数量的元素,因为总和将被应用到输入? –

+0

@NewAlexandria:当他进入每个数组时,他积累了结果,所以第一个数组不变,第二个是第一个加上自身的总和(分别为每个成员),第三个是结果的总和第二,加上自己的成员,等等。 –

+0

正确。当它传递给前一个元素的引用时,我倾向于reduce()函数。我已经看到了平面1个暗淡阵列的例子,但不能完全适应它以适应多暗淡阵列。 – Seb

回答

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] 
    } 
} 

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

+0

谢谢你们,所有可行的解决方案。我喜欢@char方法,因为它重量轻,使用香草JS和超快速。好一个。 – Seb

+0

感谢您的评论Seb。 当我选择使用库或非循环方法时,我被雇主告知,因为它们让事情变得更慢。 – char

+0

@char指导您的雇主了解更多可维护的代码和更少的错误比未测量的速度增益更重要:) – djechlin

0

这会给你所有元素的总和。并不完全符合你的要求,但我会留下这个答案给未来的访问者,他们会收到问题标题。

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

    _.flatten([1, [2, [3, [4]], 5]]); 
    // → [1, 2, [3, [4]], 5] 
    
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]] 
 
))

不同于其他的答案,这个人是不是破坏性的,保留原始阵列和返回结果。

+0

这一个不会工作,因为之前的结果不会更新。 例如,当你到达第三个数组时,第二个数组还没有被更新以包含第一个数组sum,所以你只会得到第二个数组+第三个数组值,而不是1st + 2nd + 3rd数组值。 – char

+1

@char:它确实有效,因为他从结果中取得了以前的值,而不是原来的值。 –

+1

@char https://jsfiddle.net/hojwxane/它确实有效。原因是结果数组确实存储了原始累积和,并且将下一个元素设置为结果数组的前一个元素与原始数组的下一个元素的和。 – afuous

0

这是一个多么宝贵的问题。

为什么不先调换数组? Transposing a 2D-array in JavaScript - - 对这个问题的回答暗示underscore.js解决方案:

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

做到这一点。有很多方法。

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

IMO这是一个很好的和可读的解决方案,因为“转置+总和”对于问题的列总和性质非常真实,并且我会避免一个强制性的或者循环繁重的解决方案来掩盖这一点。

+1

@ RokoC.Buljan完成 – djechlin

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) { 
 
    \t 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>';

这里有一个sligthly “优化” (golfed)版本,传递起点为减少和切片阵列

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

 
var arr2 = arr.slice(1).reduce(function(a,b) { 
 
\t 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>';