2016-03-24 65 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>';