2017-01-02 57 views
1

我在JavaScript中嘗試這種reduce時我沒有得到預期的結果:JavaScript數組減少到子數組長度 - 爲什麼這不起作用?

let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; 

x.reduce((a,b) => a.length + b.length, []); 

簡單,對不對?這是我期待的事情發生,一步一步:

---------------------------------------------------------------- 
| callback | a (accumulator) | b (currentValue) | return value | 
---------------------------------------------------------------- 
| 1st run | 0    | 3    | 3   | 
---------------------------------------------------------------- 
| 2nd run | 3    | 3    | 6   | 
---------------------------------------------------------------- 
| 2nd run | 6    | 3    | 9   | 
---------------------------------------------------------------- 

什麼我真正得到? NaN。在英語中,如果我理解正確,迭代器首先查看我給它的初始值(空數組作爲reduce的第二個參數),並由參數a表示。我的代碼顯示了一個簡單的.length兩個參數被添加。我在哪裏錯了?

+1

輸入是數組,而不是數字,您在圖表中對此進行了描述。 'a'的第一個值是'[]',而不是'0',所以'a.length'可以工作。通過返回一個數字,你會在下一次迭代中提供一個數字,並在其上調用'.length',這顯然不是你的意圖。 – meagar

+0

@meagar Yup,剛剛意識到看着下面的Pointy的代碼。謝謝! –

+1

如果你的意圖是總結數組的長度,你可以很乾淨地'map'和'reduce':'x.map(a => a.length).reduce((a,b)=> a + b )' – meagar

回答

-1

尖尖的碼以上(實際上並不返回9喜歡意)讓我來此工作的解決方案:

let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; 
x.reduce((a,b) => a + b.length, 0); 

微薄也指出,在評論認爲這是爲map/reduce組合作爲這樣一個經典案例(更圓滑的解決方案):

let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; 
x.map(a => a.length).reduce((a,b) => a + b); 
+3

當您將初始起始值設置爲零並且永遠不會從回調中返回數組時,'a'永遠不會減少數組請參閱https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce – charlietfl

+0

Meager的解決方案存在缺陷,因爲缺少初始值,因此如果數組沒有元素,則會失敗,即使這可能應該是返回零的有效輸入。 – 2017-01-02 04:46:04

+0

@torazaburo我把變量賦值放在meager的解決方案中,至少在這個特定的實例中顯示它。但有一點要說。 –

1

.reduce() API預計您的回調函數將返回累加器值(在您的情況下,起始值爲[])。你的回調只是返回一個值。

爲了讓你的代碼工作,你需要這樣的:現在

x.reduce((a,b) => { a.push(a.length + b.length); return a; }, []); 

,如果你真的是什麼數組的長度的總和,那麼你不想無論如何,它都會積聚成一個陣列。你想要一個簡單的總和。代替具有蓄能器是陣列的那麼它僅需要是數字:

var sum = x.reduce(((sum, array) => sum + array.length), 0); 

開始與零個,並且每個調用函數將陣列長度的總和。

+0

你能發表一個代碼調整來展示一個例子嗎? –

+1

@TheQodesmith只是:) – Pointy

+0

啊,我明白了。所以在我的情況下,因爲我正在累積數組長度,所以需要返回一個數組以繼續迭代以保持一致。 –

5

我想這是你想要做的(更名爲清楚起見變量)什麼:

let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; 

x.reduce((acc,element) => acc + element.length, 0); 

這是它會如何發生的一步步驟:

-------------------------------------------------------------- 
| callback | acc | element | element.length | return value | 
-------------------------------------------------------------- 
| 1st run | 0 | [1, 2, 3] | 3    | 3   | 
-------------------------------------------------------------- 
| 2nd run | 3 | [4, 5, 6] | 3    | 6   | 
-------------------------------------------------------------- 
| 3rd run | 6 | [7, 8, 9] | 3    | 9   | 
-------------------------------------------------------------- 
0

作爲替代使用reduce,壓平在陣列並採取結果的長度。

function flatten(a) { return [].concat(...a); } 
 

 
const x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; 
 
const length = flatten(x).length; 
 

 
console.log(length);

flatten實施以上是對於具有一個或兩個的深度陣列。根據需要擴展/替換更深嵌套的陣列。