【高階関数】reduceメソッドについて解説 (GAS/JavaScript) | GASおじさんのブログ
GASの基本

【高階関数】reduceメソッドについて解説 (GAS/JavaScript)

reduce GASの基本

本記事ではreduceメソッドについて解説していきます。

YouTubeでも解説していますので動画で見たい方は以下からどうぞ。

reduceメソッドの概要

reduceメソッドは、配列の各要素に対してコールバック関数を実行し、その結果を累積して1つの値を作成するメソッドです。

たとえば以下は、配列numbersの各要素の合計値を算出します。

function myFunction() {
  const numbers = [1, 2, 3, 4, 5];
  const sum = numbers.reduce(function (a, b) {
    return a + b;
  });
  console.log(sum);
}

コールバックをアロー関数で書き直すと以下のようになります。

function myFunction() {
  const numbers = [1, 2, 3, 4, 5];
  const sum = numbers.reduce((a, b) => a + b);
  console.log(sum);
}

こちらの実行結果は以下の通り。

配列numbersの要素1, 2, 3, 4, 5の合計値15が算出されました。

reduceメソッドの特徴

コールバックの引数は2つ与える

前回のsortメソッドではコールバックに2つの引数(a, b)を与えましたが、今回のreduceも同じように2つの引数を与えます。

numbers.reduce((a, b) => {});

引数名はなんでもいいですが、今回も(a, b)として説明していきます。

コールバックの返り値が次のaとなる

コールバックの返り値が次のループのaとなります。

以下の関数を実行するとわかりやすいです。

function myFunction() {
  const numbers = [1, 2, 3, 4, 5];
  const sum = numbers.reduce((a, b) => {
    console.log(a, b);
    return a + b;
  });
  console.log(sum);
}

こちらを実行結果は以下の通り。

  • 1周目のa + bの結果「3」が2周目のaとなっている
  • 2周目のa + bの結果「6」が3周目のaとなっている
  • 3周目のa + bの結果「10」が4周目のaとなっている
  • 最後のa + bの結果「15」がsumとなっている

初期値を与えることができる

reduceメソッドの第2引数で初期値を設定することができます。

function myFunction() {
  const numbers = [1, 2, 3, 4, 5];
  const sum = numbers.reduce((a, b) => {
    console.log(a, b);
    return a + b;
  }, 0);
  console.log(sum);
}

こちらの実行結果は以下の通りです。

  • 1周目のa + bの結果「1」が2周目のaとなっている
  • 2周目のa + bの結果「3」が3周目のaとなっている
  • 3周目のa + bの結果「6」が4周目のaとなっている
  • 4周目のa + bの結果「10」が5周目のaとなっている
  • 最後のa + bの結果「15」がsumとなっている

reduceメソッドの使用例

reduceメソッドでは配列の合計値を算出する以外にも、配列の最大値や最小値を求めることもできます。

配列の最大値を求める

function myFunction() {
  const numbers = [1, 2, 3, 4, 5];
  const max = numbers.reduce((a, b) => {
    if (a > b) {
      return a;
    } else {
      return b;
    }
  });
  console.log(max);
}

こちらを三項演算子を使って書き直すと以下のようになります。

function myFunction() {
  const numbers = [1, 2, 3, 4, 5];
  const max = numbers.reduce((a, b) => {
    return a > b ? a : b;
  });
  console.log(max);
}

さらにアロー関数における暗黙的なリターンを使って以下のように書き直せます。

function myFunction() {
  const numbers = [1, 2, 3, 4, 5];
  const max = numbers.reduce((a, b) => a > b ? a : b);
  console.log(max);
}

こちらの実行結果は以下の通り。

配列の要素の最大値である「5」が求められていますね。

配列の最小値を求める

最小値を求めるには、最大値を求める不等式を逆にすればいいだけです。

function myFunction() {
  const numbers = [1, 2, 3, 4, 5];
  const min = numbers.reduce((a, b) => a < b ? a : b);
  console.log(min);
}

こちらの実行結果は以下の通り。

配列の要素の最小値である「1」が求められていますね。

オブジェクトの配列に対してreduceを使う

単純な数値の配列ではなく、オブジェクトの配列に対してreduceを使ってみましょう。

たとえば以下のようにすると、一番年上のユーザーと、一番年下のユーザーを求めることができます。

function myFunction() {
  const users = [
    { name: '佐藤', age: 25 },
    { name: '鈴木', age: 18 },
    { name: '高橋', age: 32 },
    { name: '田中', age: 20 },
    { name: '伊藤', age: 34 },
  ];
  const oldest = users.reduce((a, b) => a.age > b.age ? a : b);
  const youngest = users.reduce((a, b) => a.age < b.age ? a : b);
  console.log(oldest);
  console.log(youngest);
}

こちらの実行結果は以下の通り。

なぜ「reduce」と言うのだろう?

なぜreduceというのでしょうか?

reduceは「減らす」という意味がありますよね。

しかし、上記の例にも出したように、reduceメソッドでは配列の合計値を求めることができます。

「合計値を求めるって、むしろ増やしてるじゃん」ということで、直感に反する名前になっているように感じるかもしれません。

これは、「縮小する」「集約する」というreduceの意味に由来しているためこのような名前となっています。

たとえば、今まで学習してきたmapやfilterという高階関数では、その返り値として配列が返ってきていました。

function myFunction() {
  const users = ['佐藤', '鈴木', '高橋'];
  const respectedUsers = users.map(user => user + 'さん');
  console.log(respectedUsers);
}
  • mapメソッドの結果は[ ‘佐藤さん’, ‘鈴木さん’, ‘高橋さん’ ]
function myFunction() {
  const users = ['佐藤', '鈴木', '高橋', '田中', '伊藤'];
  const filteredUsers = users.filter(user => user.includes('藤'))
  console.log(filteredUsers);
}
  • flterメソッドの結果は[ ‘佐藤’, ‘伊藤’ ]

このように、それぞれのメソッドの結果として配列が返ってきています。

一方、今回のreduceでは、reduceメソッドの結果として配列ではなく、一つの値として返ってきています。

function myFunction() {
  const numbers = [1, 2, 3, 4, 5];
  const sum = numbers.reduce((a, b) => a + b);
  console.log(sum);
}
  • reduceメソッドの結果は「15」

[1, 2, 3, 4, 5]という配列に対してreduceメソッドを使った結果、「15」という一つの値を返しています。

このようにreduceメソッドは、配列の要素を順番に処理しながら累積的に一つの値に「縮小(reduce)」していくため、このように名付けられています。

まとめ

以上、reduceメソッドについて解説しました。

reduceメソッドはこれまで紹介した高階関数と比べると、ちょっと難易度の高いメソッドですね。

reduceという名前に反して合計値を求めることができるというややこしさも相まって、多少理解に苦しむかもしれません。

最大値、最小値を求める場合は三項演算子についても理解しておかないといけないので、それもより一層難しく感じさせるポイントです。

しかし、1個1個分解していけば必ず理解できるはずです。

なんども手元で実行してみて、その仕組みを深く理解し、使いこなせるようになっておきましょう。

連載目次: 高階関数シリーズ

  1. 【高階関数】forEachメソッドについて解説 (GAS/JavaScript)
  2. 【高階関数】mapメソッドについて解説 (GAS/JavaScript)
  3. 【高階関数】filterメソッドについて解説 (GAS/JavaScript)
  4. 【高階関数】sortメソッドについて解説 (GAS/JavaScript)
  5. 【高階関数】reduceメソッドについて解説 (GAS/JavaScript)
  6. 【高階関数】findとfindIndexについて解説 (GAS/JavaScript)
  7. 【高階関数】everyとsomeについて解説 (GAS/JavaScript)
  8. 関数宣言・関数式・アロー関数 (GAS/JavaScript)

コメント

タイトルとURLをコピーしました