JavaScript reduce の使い方 #1

株式会社リュディアです。2日間、お休みをいただきましたが再開します。JavaScript でサポートしている高階関数の1つである reduce メソッド(以下、reduce ) についてまとめてみます。掲載するソースコードはすべて GAS の開発環境で動作確認をしています。

以前に高階関数 map も以下の3つの記事にまとめています。これらを先に読んでいただいている前提で reduce についてのまとめを行います。
JavaScript map の使い方 #1
JavaScript map の使い方 #2
JavaScript map の使い方 #3

map は対象となる元配列にコールバック関数で定義されている操作を行い、元配列と同じ要素数の配列を戻り値としました。一方で reduce は対象となる元配列にコールバック関数で定義されている操作を行い、単一の値を戻り値とします。単一の値と記載しましたが配列等も単一の値と考えます。

ではさっそく例をみていきましょう。map のまとめと同様に最初の例では reduce の動きを見るためにコールバック関数の引数をすべて記載しています。

function myFunction1() {
 const inputArray = [ 1, 3, 10, 17, 20, 31 ] ;

 inputArray.reduce( function( accumulator, currentValue, index, array ) {
                      console.log( accumulator, currentValue, index, array ) ;
                    } );
}

// 実行結果
// accumulator currentValue index array
// 1            3           1     [ 1, 3, 10, 17, 20, 31 ]
// undefined   10           2     [ 1, 3, 10, 17, 20, 31 ]
// undefined   17           3     [ 1, 3, 10, 17, 20, 31 ]
// undefined   20           4     [ 1, 3, 10, 17, 20, 31 ]
// undefined   31           5     [ 1, 3, 10, 17, 20, 31 ]

まず最初に気づくのはコールバック関数で利用可能な引数個数が map と reduce で異なることですね。map では 3つの引数を利用可能でしたが、reduce では4つの引数を利用可能です。currentValue, index, array は map と同様ですが問題は accumulator です。accumulator はアキュムレーターまたは累積値と呼ばれるもので、過去の演算結果を積み上げたものに対して使われます。また配列の要素数が6であるのに対して実行回数が5回であることにも注意してください。reduce の動きを以下の図を使って説明していきます。

例1

初回の実行では、accumulator に元配列のインデクス0の要素 "1" が設定され、currentValue には元配列のインデクス1の要素 "3" が設定されます。2回目からは accumulator は undefined となり、currentValue には元配列のインデクス 2 以降が順次設定されていきます。accumulator が undefined(未定義) となっている理由は後述します。このように初回のみ元配列のインデクス0, 1 の要素を利用するため実行回数は元配列の要素数より1だけ少なくなります。

では、この動きを利用して配列の要素の総和を求める関数を作ってみましょう。以下にソースコードと実行結果を示します。

function sumByReduce() {
 const inputArray = [ 1, 3, 10, 17, 20, 31 ] ;

 inputArray.reduce( function( accumulator, currentValue, index, array ) {
                      console.log( accumulator, currentValue, index, array ) ;
                      return accumulator + currentValue ;
                    } );
}

// 実行結果
// accumulator currentValue index array
//  1           3           1     [ 1, 3, 10, 17, 20, 31 ]
//  4          10           2     [ 1, 3, 10, 17, 20, 31 ]
// 14          17           3     [ 1, 3, 10, 17, 20, 31 ]
// 31          20           4     [ 1, 3, 10, 17, 20, 31 ]
// 51          31           5     [ 1, 3, 10, 17, 20, 31 ]

今回はコールバック関数の戻り値を accumulator + currentValue と定義しました。動きを以下の図を使って説明していきます。

例2

初回は accumulator = 1、currentValue = 3 なので戻り値は 1 + 3 = 4 になりますが、この戻り値 4 が次回の accumulator にセットされていることがわかります。先の例では accumulator の値が undefined(未定義) になっていましたが、戻り値を定義していなかったためです。この例では accumulator + currentValue を戻り値として accumulator に累積していくことで元配列の要素の和が順次計算されている様子がわかります。

高階関数 reduce の基本的な動きは理解できたでしょうか。今後、何度かにわけて reduce の動きを丁寧にまとめていきたいと思います。ここで1つ宿題を出しておきます。配列のすべての要素を2倍した値の合計を求める関数を考えてみてください。今回まとめた reduce の使い方では不便であることを実感しておいてもらえたらと思います。

では、ごきげんよう。


この記事が気に入ったらサポートをしてみませんか?