【JavaScript】reduce()で配列の畳み込み処理を簡単に実装する【コピペでOK】

みなさんこんにちは!

今回の記事は、

悩みを抱えた人
・JavaScriptのreduce()メソッドの使い方が知りたい!
・reduce()メソッドは引数が多すぎてよく分からない…
・reduce()メソッドを使った実践例を見てみたい!

というお悩みを解決する記事になっています。


この記事の内容

・reduce()メソッドの基本的な使い方
・reduce()メソッドの簡単な実装例【コールバック関数の戻り値を追っていきます】
・reduce()メソッドの実践例【最大値・最小値も取得できます】


レバテックフリーランス … 業界最大級の案件数業界トップクラスの高単価報酬を誇る最大手のサービスです。実績豊富なコーディネーターが丁寧な対応をしてくれるため、案件の無理な提案はありません。フリーランスで生きていくためにはまず登録しておきましょう。
MidWorks … フリーランス賠償責任保障生命保険の折半など、フリーランスでありながらも正社員並みの保障を受けられるのが特徴です。また、経験豊富なキャリアコンサルタントによる手厚いサポートも受けられるため、安定したフリーランス生活を送りたい方には特におすすめのサービスです。
ポテパンフリーランス … IT業界・技術に詳しいコンサルタントが担当してくれるため、こちらの要望をきちんと理解した上で案件を紹介してくれます。また、案件情報のみならず、フリーランスのイロハについても教えてくれるため、フリーランスとして初めて活動される方には特におすすめのサービスです。

レバテックキャリア … ITエンジニアが利用したい転職エージェントNo.1にも選ばれており、年収600万円以上のハイクラス求人を5,000件以上も保有しています。エンジニアが転職を考えた時にまず初めに登録しておくべきサービスです。
Tech Stars Agent … Tech Stars Agentでは、担当エージェントが全員エンジニア出身のため、スキルやキャリアを見据えたきめ細かな転職支援が受けられます。運営元の株式会社Branding Engineerは、独立支援サービス「MidWorks」も展開しているため、独立を視野に入れたサポートも受けられます
転職ドラフト … 年収UP率93.8%/平均年収UP額126万円と圧倒的な年収UP率を誇るイベント型のエンジニア向け 転職サービスです。毎月1回開催され、厳選された優良IT/Web系企業約150社からダイレクトスカウトを受け取ることができます。年収アップを目指す方は登録必須です。


reduce()メソッドの基本的な使い方

reduce()メソッドは、配列処理向けのメソッドの1つです。

配列の要素を順番に取り出し、引数で定義した処理を適用しながら、ある1つの値を算出する機能を持ちます。

reduce()メソッドは、コールバック関数を含めて引数の数が多く、ひと目見ただけではどのように動作するのかが把握しづらいです。

したがって、まずは引数一つ一つの意味について解説しましょう。

reduce()メソッドの引数と戻り値

reduce()メソッドの引数は以下の2つです。

必須or任意役割
コールバック関数必須配列に格納されている要素に対して適用する処理を定義
初期値任意(省略可)コールバック関数の初回呼び出し時に設定する値

第一引数であるコールバック関数は、reduce()メソッドの処理の中核ともいえるべき要素です。

このコールバック関数の引数も数が多くややこしいため、次節でその内容を見ていきましょう。

コールバック関数の引数

コールバック関数は、4つの引数を持つように実装しなければなりません。

各引数の意味は以下の通りです。

必須or任意役割
アキュムレータ必須 コールバック関数の計算結果が格納される。
コールバック関数の初回呼び出し時は、reduce()メソッドの第二引数である初期値が格納される。
現在の値必須添え字の若い順に配列の要素が1つずつ格納される。
添字任意(省略可)第二引数の値に対応する配列の添字が格納される。
配列任意(省略可)配列がそのまま格納される。

次の節で、具体例を挙げながらreduce()メソッドの動作を詳しく見てみましょう。

reduce()メソッドの実装コード

例として、「配列に格納されている数値の合計値を導き出す処理」をreduce()メソッドで実装してみましょう。

実装コードは以下のサンプルコードの通りです。

// 計算対象の配列(合計値:15)
sample_data_list = [3, 1, 4, 2, 5];

// 要素を足し算する処理をコールバック関数で定義
callback_func = function(acc, current, index, array) {
  console.log("●途中計算結果:" + acc + ", 現在の値:" + current + ", インデックス:" + index);
  return acc + current;
};

// reduce()メソッドにコールバック関数と初期値を渡す
sum = sample_data_list.reduce(callback_func, 0);

console.log("結果:" + sum); // 結果:15

サンプルコードを実行するとコンソール上には、以下の通り出力されます。

●途中計算結果:0, 現在の値:3, インデックス:0
●途中計算結果:3, 現在の値:1, インデックス:1
●途中計算結果:4, 現在の値:4, インデックス:2
●途中計算結果:8, 現在の値:2, インデックス:3
●途中計算結果:10, 現在の値:5, インデックス:4
結果:15

コールバック関数内で定義したコンソール出力処理が5回実行されていることが分かります。

初回の呼び出し時から、reduce()メソッドの動作について詳しく確認しましょう。

コールバック関数の初回の格納値

初めてコールバック関数が呼び出されたときは、各引数に以下のように値が格納されています。

アキュムレータ現在の値添字
030

添え字の若い順で配列の要素を取り出すため、コールバック関数の初回呼び出し時は1番目の要素である、3」が設定されます。

また、アキュムレータにはreduce()メソッドの第二引数で設定されている「0」が格納されてます。

コールバック関数の処理内容は単純で、アキュムレータと要素の値を足した値を導き出すだけです。

したがって、コールバック関数の戻り値は、「0+3=3」となります。

なお、reduce()メソッドの第二引数を省略した場合、初回呼び出し時の引数は以下のように値が設定されます。

アキュムレータ現在の値添字
311

初期値が省略された場合は、例外として、アキュムレータに1番目の要素現在の値に2番目の要素が格納されます。

それ以外について、計算方法や計算結果に違いはありません。

コールバック関数の2回目の格納値

コールバック関数の2回目呼び出し時、引数は以下の通り設定されます。

アキュムレータ現在の値添字
311

配列の1番目の要素が処理され、2番目の要素に移ります。

したがって、今回は「1」が主役です。

アキュムレータは、途中の計算結果、言い換えると前回呼び出したときの戻り値がそのまま設定されるため、「3」となります。

コールバック関数の処理内容自体は変化はないので、「3+1」が実行されて「4」が戻り値となって、2回目の実行は完了です。

コールバック関数の3回目以降の格納値

3回目以降のコールバック関数呼び出し時の引数設定値は、以下の通りです。

アキュムレータ現在の値添字
3回目442
4回目823
5回目1054

reduce()メソッドの最終的な計算結果

配列に格納されているすべての要素について処理が完了したら、最後に呼び出したときの戻り値がそのままreduce()メソッドの戻り値となります。

したがって、今回の例では、戻り値は5回目に呼び出したときの「10+5」の計算結果である「15」です。

reduce()メソッドを使った実践例

reduce()メソッドをうまく使えば、配列の合計値を計算する以外にも、コールバック関数の実装次第でさまざまな処理を実装できます。

続いては、reduce()メソッドの実践例を3つ紹介していきます。

reduce()メソッドで各要素を累乗した配列を生成する

配列の各要素を累乗した配列を新たに生成するには、以下のように実装します。

// 計算対象の配列
sample_data_list = [6, 8, 4, 7, 5];

// コールバック関数
callback_func = function(acc, current, index) {
  // 2乗した値を新しい配列に設定
  acc[index] = current * current;
  return acc;
};

// 空の配列を初期値として呼び出す
sqr_data_list = sample_data_list.reduce(callback_func, []);

console.log(sqr_data_list); // 結果:[36, 64, 16, 49, 25]

初期値に空の配列を渡すことで、コールバック関数内で要素を次々と挿入することができます。

アキュムレータ自体をコールバック関数の戻り値とすることがポイントです。

reduce()メソッドで最大値・最小値を取得する

コールバック関数で、値の大小を比較して大きい方、または小さい方を戻り値にするようにすれば、配列の中から最大値・最小値を取得する処理を実装できます。

// 計算対象の配列
sample_data_list = [6, 4, 8, 7, 5];

// コールバック関数
callback_func = function(acc, current) {
  // 前回までで取得した最大値と現在の値を比べ、大きい方(小さい方)を戻り値とする
  // 不等号の向きを変えることで、最小・最大の切り替えが可能
  return acc < current ? current : acc;
};

result = sample_data_list.reduce(callback_func);

console.log(result); // 結果:8(最大値)、4(最小値)

処理の流れとして、コールバック関数を要素ごとに実行する中で、値が最大(最小)のものがアキュムレータに常時格納され、三項演算子を使った値の比較によって、戻り値を変えています。

reduce()メソッドで要素の絞り込む

コールバック関数で条件を記述し、新しく配列を作成するような処理を実装することで、配列内から特定の要素のみを取得することができます。

// 計算対象の配列
sample_data_list = [20, 48, 120, 258, 25, 37, 84, 301];

// 100以上の値を抽出するコールバック関数
callback_func_1 = function(acc, current) {
  if (current >= 100) acc[acc.length] = current;
  return acc;
};

result_array_1 = sample_data_list.reduce(callback_func_1, []);

console.log(result_array_1); // 結果:[120, 258, 301]

// 奇数の値を抽出するコールバック関数
callback_func_2 = function(acc, current) {
  if (current % 2 == 1) acc[acc.length] = current;
  return acc;
};

result_array_2 = sample_data_list.reduce(callback_func_2, []);

console.log(result_array_2); // 結果:[25, 37, 301]

reduce()メソッドを使う際の注意点

最後に、reduce()メソッドを使う際の注意点について解説していきます。

配列が空で初期値がない場合にはエラーが発生する

配列が空である場合、reduce()メソッドの初期値を省略した状態で呼び出すと、エラーが発生します

以下のサンプルコードで、エラーになることを確認しましょう。

// 計算対象の配列
sample_data_list = []

callback_func = function(acc, current) {
  return acc + current;
};

// 初期値なしで呼び出した場合
result_array_1 = sample_data_list.reduce(callback_func);
// Uncaught TypeError: Reduce of empty array with no initial value

console.log(result_array_1);

一方、初期値を設定しておけばエラーになることはありません。

添字の大きい順で処理する時はreduceRight()を使う

reduce()メソッドとは別に、添字の大きい方から処理を行うreduceRight()メソッドが別途用意されています。

メソッド名と機能が異なること以外、引数などの意味に違いはありません

「2. reduce()メソッドの動作の詳細」で示したサンプルコードについて、reduce()からreduceRight()メソッドに変更して実行すると、以下のような結果が得られます。

●途中計算結果:0, 現在の値:5, インデックス:4
●途中計算結果:5, 現在の値:2, インデックス:3
●途中計算結果:7, 現在の値:4, インデックス:2
●途中計算結果:11, 現在の値:1, インデックス:1
●途中計算結果:12, 現在の値:3, インデックス:0
結果:15

初回呼び出し時に、配列の一番最後の要素が引数として設定され、添字の大きい順に足し算が行われていることが分かります。

結局の所、合計値を導き出していることに変わりはなく、最終結果もreduce()メソッド利用時と変わりません。

お仕事の途中ですが、少し一休みして、転職独立について考えてみませんか🙌?

現役エンジニアが選ぶおすすめの転職エージェント11選【成功談・失敗談もあります】

レバテックフリーランスの評判ってどう?【現役エンジニアが徹底解説します】

MidWorks(ミッドワークス)の評判ってどう?【現役エンジニアが徹底解説します】

日々の業務に追われて自分を見失わないよう、
定期的にキャリアを振り返るようにしておきましょう🤲

最後に

さて、ここまでJavaScriptのreduce()メソッドの使い方や実践例について解説してきましたが、いかがでしたか?

コールバック関数を含め、reduce()メソッドを使用するにはそれぞれの引数の役割をきちんと理解していなければなりません

非常に便利なメソッドではありますが、reduce()メソッドを使いこなすには少し慣れが必要です。

今回の記事でご紹介した実装例を参考にしていただき、「こういう実装できないかな?」とご自身でも色々と挑戦してみてくださいね。

このブログを通じて少しでも「傍(はた)を楽(らく)にする」ことができていれば嬉しく思います。

最後まで読んでいただきましてありがとうございました。