JavaScript reduce の使い方 #2
株式会社リュディアです。JavaScript reduce の使い方 #2 です。JavaScript reduce の使い方 #1 の続きになります。掲載するソースコードはすべて GAS の開発環境で動作確認をしています。
JavaScript reduce の使い方 #1 で宿題とした「配列のすべての要素を2倍した値の合計を求める関数」を考えてみます。次の例では currentValue * 2 を accumulator に順次加算して戻り値とするのでうまく動作しそうに見えますが誤りが含まれます。
function sumX2ByReduceWrong() {
const inputArray = [ 1, 3, 10, 17, 20, 31 ] ;
inputArray.reduce( function( accumulator, currentValue, index, array ) {
console.log( accumulator, currentValue, index, array ) ;
return accumulator + currentValue * 2 ;
} );
}
// 実行結果
// accumulator currentValue index array
// 1 3 1 [ 1, 3, 10, 17, 20, 31 ]
// 7(1+3x2) 10 2 [ 1, 3, 10, 17, 20, 31 ]
// 27(7+10x2) 17 3 [ 1, 3, 10, 17, 20, 31 ]
// 61(27+17x2) 20 4 [ 1, 3, 10, 17, 20, 31 ]
// 101(61+20x2) 31 5 [ 1, 3, 10, 17, 20, 31 ]
誤りに気付きましたか?最初に accumulator に設定される元配列のインデクス 0 の要素 1 が 2倍されずに加算されています。以下の図を見てください。
元配列のインデクス 1 の要素 3 は 2倍されて 6 が加算されていますが、元配列のインデクス 0 の要素 1 はaccumulator に設定されるので currentValue * 2 の式に該当することなく加算されます。そのため誤りが発生します。どうすればよいのでしょうか?
function sumX2ByReduceCorrect() {
const inputArray = [ 1, 3, 10, 17, 20, 31 ] ;
inputArray.reduce( function( accumulator, currentValue, index, array ) {
console.log( accumulator, currentValue, index, array ) ;
return accumulator + currentValue * 2 ;
}, 0 );
}
// 実行結果
// accumulator currentValue index array
// 0 1 0 [ 1, 3, 10, 17, 20, 31 ]
// 2(0+1x2) 3 1 [ 1, 3, 10, 17, 20, 31 ]
// 8(2+3x2) 10 2 [ 1, 3, 10, 17, 20, 31 ]
// 28(8+10x2) 17 3 [ 1, 3, 10, 17, 20, 31 ]
// 62(28+17x2) 20 4 [ 1, 3, 10, 17, 20, 31 ]
// 102(62+20x2) 31 5 [ 1, 3, 10, 17, 20, 31 ]
前の例と比較してみてください。同じ元配列を使っていますが実行結果が 6 行になっているのがわかりますか?また初回の実行では accumulator = 0 で、currentValue にインデクス 0 の要素 1 が設定されているのがわかりますか?これは、inputArray.reduce ( function(...) {...} , 0 ); の記述で accumulator の初期値を設定しているためです。単に加算をするだけであればこの項は不要なのですが、accumulator に初期値を設定したほうがプログラム全体がシンプルになることが多いです。慣れるまでは accumulator の初期値を設定する記述をこころがけてください。今回のように数値、ここでは 0 を初期値としましたが、ヌル配列 [ ] を設定することもあります。これは次回でまとめてみたいと思います。
JavaScript reduce の使い方 #2 では accumulator の初期値の与え方をまとめてみました。ここまでくれば reduce の使い方はほぼ終了です。次回は戻り値として配列を扱ってみます。
では、ごきげんよう。