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

みなさんこんにちは!

今回の記事は、

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

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


この記事の内容

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


フリーランス案件を探すならこのエージェント!

運営会社 レバテック株式会社 株式会社Branding Engineer 株式会社Hajimari
対応エリア 東京・神奈川・埼玉・千葉
大阪・兵庫・京都・愛知・福岡
東京・神奈川・埼玉・千葉
大阪・兵庫・京都・奈良・和歌山・滋賀
東京・神奈川・埼玉・千葉
茨城・大阪・兵庫・福岡
案件数 約28,000件 約3,300件 約4,200件
平均単価 68.2万円 72.2万円
最高月収 145万円 200万円 176万円
特徴高単価な案件が多い
福利厚生サービスが受けられる
・首都圏の案件が中心
給与保証制度で安定した収入を得られる
・税務処理のサポートあり
・マージン率は実質20%
週2/週3の案件が多い
在宅/リモート案件が多い
・スタートアップ企業やベンチャー企業の案件が多い
紹介企業例 ・株式会社Gunosy
・株式会社バンダイナムコホールディングス
・株式会社ユーザベース
・Sansan株式会社
・株式会社一休
・株式会社FiNC Technologies など
・クックパッド株式会社
・株式会社カオナビ
・株式会社Kaizen Platform など
説明記事
公式サイト


転職を考えているならこのエージェント!

運営会社 レバテック株式会社 株式会社Branding Engineer 株式会社リブセンス
対応エリア 東京・神奈川・埼玉・千葉
大阪・兵庫・京都・愛知・福岡
東京・神奈川・埼玉・千葉
大阪・兵庫・京都・奈良・和歌山・滋賀
東京・神奈川・埼玉・千葉
茨城・大阪・兵庫・福岡
案件数 約13,000件 約800件
※非公開求人が多い

※ドラフト制のため、対象外
年齢層 20代:◎
30代:〇
40代:〇
20代:〇
30代:〇
40代:△
20代:〇
30代:〇
40代:〇
特徴エンジニア・デザイナーを専門としている
・カウンセリングに時間をかける
年収アップ率60%の実績
IT/Web/ゲーム業界専門の転職エージェント
・業界経験者がキャリアコンサルタントを務める
・丁寧なカウンセリングで入社後の離職率1%以下を実現
ドラフト制による採用を叶える特殊なサービス
スキル・経験重視で評価してもらえる
・他エンジニアの入札結果を見ることで
自分の市場価値が分かる
紹介企業例 ・サイボウズ株式会社
・株式会社サイバーエージェント
・Chatwork株式会社 など
・DMM.com
・Money Forward
・SmartHR など
・メルカリ
・ZOZOテクノロジーズ
・freee など
説明記事
公式サイト


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()メソッド利用時と変わりません。

最後に

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

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

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

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

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

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


フリーランス案件を探すならこのエージェント!

運営会社 レバテック株式会社 株式会社Branding Engineer 株式会社Hajimari
対応エリア 東京・神奈川・埼玉・千葉
大阪・兵庫・京都・愛知・福岡
東京・神奈川・埼玉・千葉
大阪・兵庫・京都・奈良・和歌山・滋賀
東京・神奈川・埼玉・千葉
茨城・大阪・兵庫・福岡
案件数 約28,000件 約3,300件 約4,200件
平均単価 68.2万円 72.2万円
最高月収 145万円 200万円 176万円
特徴高単価な案件が多い
福利厚生サービスが受けられる
・首都圏の案件が中心
給与保証制度で安定した収入を得られる
・税務処理のサポートあり
・マージン率は実質20%
週2/週3の案件が多い
在宅/リモート案件が多い
・スタートアップ企業やベンチャー企業の案件が多い
紹介企業例 ・株式会社Gunosy
・株式会社バンダイナムコホールディングス
・株式会社ユーザベース
・Sansan株式会社
・株式会社一休
・株式会社FiNC Technologies など
・クックパッド株式会社
・株式会社カオナビ
・株式会社Kaizen Platform など
説明記事
公式サイト


転職を考えているならこのエージェント!

運営会社 レバテック株式会社 株式会社Branding Engineer 株式会社リブセンス
対応エリア 東京・神奈川・埼玉・千葉
大阪・兵庫・京都・愛知・福岡
東京・神奈川・埼玉・千葉
大阪・兵庫・京都・奈良・和歌山・滋賀
東京・神奈川・埼玉・千葉
茨城・大阪・兵庫・福岡
案件数 約13,000件 約800件
※非公開求人が多い

※ドラフト制のため、対象外
年齢層 20代:◎
30代:〇
40代:〇
20代:〇
30代:〇
40代:△
20代:〇
30代:〇
40代:〇
特徴エンジニア・デザイナーを専門としている
・カウンセリングに時間をかける
年収アップ率60%の実績
IT/Web/ゲーム業界専門の転職エージェント
・業界経験者がキャリアコンサルタントを務める
・丁寧なカウンセリングで入社後の離職率1%以下を実現
ドラフト制による採用を叶える特殊なサービス
スキル・経験重視で評価してもらえる
・他エンジニアの入札結果を見ることで
自分の市場価値が分かる
紹介企業例 ・サイボウズ株式会社
・株式会社サイバーエージェント
・Chatwork株式会社 など
・DMM.com
・Money Forward
・SmartHR など
・メルカリ
・ZOZOテクノロジーズ
・freee など
説明記事
公式サイト