🐈

JavaScriptのreduce()がチョットワカル

に公開2

初めに

仕事でjsを使用している際に、reduceについてあまり理解できていなかったなと思い、知識整理のため記事を作成しました。

reduceとは

reduceは、配列に対して指定した関数を実行して、一つの値にまとめて返すメソッドのことである。

例えば、for文で配列の数字を全て足し合わせて、それを変数に代入すると下記の通りになる。

const nums = [1, 2, 3, 4, 5];
let sum = 0;

for (const num of nums) {
  sum += num;
}

console.log("合計 : ", sum) // 合計 : 15

これをreduceを使用すると、次のように記述できる。

const nums = [1, 2, 3, 4, 5];
const sum = nums.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
console.log("合計 : ", sum); // 合計 : 15

上記のreduceでは、次のように処理される。

  1. 変数accumulatorに初期値 0 を代入
  2. 変数currentValueにnums[0]の 1 を代入
  3. accumulator + currentValue を行う (1回目 : 0 + 1 = 1)
  4. 計算結果の 1 をaccumulatorに代入
  5. numsの次の値 2 をcurrentValueに代入
  6. accumulator + currentValue を行う (2回目 : 1 + 2 = 3)
  7. accumulator + currentValue を行う (3回目 : 3 + 3 = 6)
  8. accumulator + currentValue を行う (4回目 : 6 + 4 = 10)
  9. accumulator + currentValue を行う (5回目 : 10 + 5 = 15)
  10. 変数sumに 15 を代入

つまり、一文でfor文と同じように処理を行っている。
この際に使用される値は次の部分に当てはまる。

const sum = arr.reduce((accumulator, currentValue) => 
    accumulator + currentValue, 
    initialValue);

reduce(〇〇〇) ... reduceメソッドのコールバック関数(この内容をもとに実行しますよという宣言)
accumulator ... 前回のreduceで処理した結果の値
currentValue ... 配列arrから1つずつ渡される値
initialValue ... 初期値

最初のループでは、配列の1個目がcurrentValueに代入され、initialValueがaccumulatorに代入される。
配列の2個目がcurrentValueに代入され、配列1個目で計算されたaccumulator + currentValueがaccumulatorに代入される。
以降は同じように処理される。

もしinitialValueの指定がなかった場合、

  1. 配列が2個以上の場合 ... 配列の1つ目の値を初期値として使用(accumulatorに配列[0]が代入)
  2. 配列が1個の場合 ... 配列の1つ目の値を初期値として使用(accumulatorに配列[0]が代入)
  3. 配列が0個の場合 ... TypeErrorになる

配列処理におけるfor文とreduceメソッドの使い分け

for文は、記述が長くなる分、わかりやすい見た目になる。
最終的に複数の値を必要とする場合などに向いている。

一方でreduceメソッドは、配列に対して一つの値にまとめることに特化している。
1つの配列を加工して、最終的に1つの値や1つの配列、1つのオブジェクトなどにしたい場合に向いている。

発展

reduceの引数には次のように記述できる。

const sum = arr.reduce((accumulator, currentValue, currentIndex, array) => {
  const reduceSum = accumulator + currentValue;
  const arrayNow = array[currentIndex];
  console.log(`配列の${currentIndex + 1}個目の値は、${arrayNow}です。`);

  return reduceSum;
}, initialValue);

currentIndex ... reduceの中で実行した回数
array ... reduceの対象となっている配列(上記の場合は配列arrの部分が該当する)

例えば、const arr = [1, 2, 3];であるとき、reduce内のconsole.logは、

配列の1個目の値は、1です。
配列の2個目の値は、2です。
配列の3個目の値は、3です。

のように出力される。

また、reduce()のコールバック関数内で複雑に処理を行う場合は、returnを使用して値を返す必要がある。

GitHubで編集を提案

Discussion

junerjuner

今なら Iterator にも reduce() がありますね

Array.from({length:40}, (_,index) => index + 1).values().reduce((s,n) => s + n,0);
// -> 820