5.3 配列の変換と集計

配列のデータを別の形に変換したり、1 つの値にまとめたりする操作について学びます。

5.3.1 map(復習)

map メソッドは、前章でも学習しましたが、配列の各要素を別の値に変換します。

const prices = [100, 200, 300];
const taxIncluded = prices.map(price => price * 1.1); // [110, 220, 330];

元の配列と同じ長さの新しい配列を作成します。 データベースから取得したデータを画面表示用に整形する際などに頻繁に使用されます。

5.3.2 reduce

reduce メソッドは、配列の要素を 1 つの値にまとめ上げる強力なメソッドです。

書式:reduce

配列.reduce((累積値, 現在の要素) => 累積値と現在の要素を使った処理, 初期値);

reduce には 2 つの引数を渡します。

第 1 引数:コールバック関数

配列の各要素に対して繰り返し実行される処理です。
コールバック関数自体が「累積値」と「現在の要素」の 2 つを引数に取ります。
処理結果が次のステップの「累積値」として引き継がれます。

第 2 引数:初期値

最初のステップで「累積値」として使われる値です。
合計を求めたいときは 0、配列を作りたいときは [] を指定します。

ソースフォルダ:public/ch05

ファイル名:array-reduce.js

➢ array-reduce.html

前の章で作った ch05/array-find.html をコピーし、ch05 にペーストしてください。 その際に、ファイル名を array-reduce.html に変更します。
ファイル内の array-find.html や array-find.js の記述も、array-reduce.html や array-reduce.js に修正します

➢ array-reduce.js

// array-reduce.js

// 商品の価格リスト
const prices = [100, 250, 180, 320];

// reduce:合計金額を計算
const total = prices.reduce((sum, price) => sum + price, 0);

alert("合計金額: " + total + "円");  // 850円

実行結果

解説

4 行目で、商品の価格を格納した配列を定義しています。

4: const prices = [100, 250, 180, 320];

7 行目では、reduce メソッドを使って、配列内のすべての価格を合計しています。

7: const total = prices.reduce((sum, price) => sum + price, 0);

このサンプルコードを書式に当てはめると、次のように対応しています。

prices.reduce( (sum, price) => sum + price , 0 );
第 1 引数:コールバック関数 第 2 引数:初期値

コールバック関数の引数 sum が「累積値」、price が「現在の要素」です。
各ステップで「sum + price」を計算した結果が、次のステップの sum として引き継がれます。
初期値の 0 が、最初のステップの sum の出発点になります。

実行の流れ

最後のステップの計算結果 850 が、total に代入されます。

reduce の第 2 引数(初期値)の重要性

先ほどのプログラムでは、reduce の第 2 引数に「0」を指定していました。 この初期値は省略することも可能ですが、常に指定することを強く推奨します。

// 第 2 引数あり(推奨)
const total = prices.reduce((sum, price) => sum + price, 0);
// 第 2 引数なし(非推奨)
const total = prices.reduce((sum, price) => sum + price);

初期値を省略した場合の挙動:

  • 配列の最初の要素が初期値として使われる
  • 空配列の場合はエラーになる
  • 予期しない動作の原因になりやすい

初期値を指定するメリット:

  • 空配列でも安全に動作する
  • コードの意図が明確になる
  • 初期値の型を変えることで、様々な処理が可能になる

reduce の応用例

reduce は合計計算以外にも、初期値の型を変えることで様々な処理を実現できます。 いくつか実用的な例を見ていきましょう。

応用例 1:平均値の計算

配列の合計を求めた後、要素数で割ることで平均値を計算できます。

const scores = [80, 90, 75, 85];

// まず合計を求める
const total = scores.reduce((sum, score) => sum + score, 0);

// 要素数で割って平均を計算
const average = total / scores.length;

console.log("平均点: " + average); // 82.5

応用例 2:最大値・最小値の取得

累積値と現在の要素を比較することで、最大値や最小値を見つけられます。

const numbers = [42, 15, 88, 23, 91, 7];

// 最大値を見つける
const max = numbers.reduce((maxValue, num) => {
    if (num > maxValue) {
        return num;
    } else {
        return maxValue;
    }
}, numbers[0]); // 最初の要素を初期値にする

console.log("最大値: " + max); // 91

応用例 3:配列からオブジェクトを生成(重複カウント)

初期値にオブジェクト {} を指定することで、配列の各要素を集計できます。

const fruits = ["りんご", "バナナ", "りんご", "みかん", "バナナ", "りんご"];

const count = fruits.reduce((acc, fruit) => {
    // そのフルーツのカウントがあれば +1、なければ 1 を設定
    acc[fruit] = (acc[fruit] || 0) + 1;
    return acc;
}, {}); // 初期値は空のオブジェクト

console.log(count);
// 結果: { りんご: 3, バナナ: 2, みかん: 1 }

※ この例では、6 章で学習するオブジェクトを使用しています。 今は「reduce を使うとこんなこともできる」という雰囲気を掴んでおき、 6 章を学習した後で改めて見直してみましょう。

ポイント

  • 第 2 引数(初期値)は空配列への対応やコードの可読性向上のため、省略せずに明示的に指定しましょう。
  • 初期値の型を変えることで、様々な処理が可能
    • 数値 0 → 合計、平均、最大・最小
    • オブジェクト {} → データの集計、グルーピング
    • 配列 [] → フィルタリング、変換、フラット化
  • reduce は map や filter と組み合わせることで、複雑なデータ処理も簡潔に記述できる、配列を「1 つの値」にまとめる万能ツールです。