1. 作品 5 件を集計する
  2. 1 件だけならその作品が最大になる
  3. 表示回数がすべて 0 なら先頭が選ばれる
  4. 空配列なら 0 件の結果を返す
コース一覧
モダンJavaScript:データ処理とコード設計
reduce でひとつにまとめる

モダンJavaScript:データ処理とコード設計

配列の map・filter・reduce・sort、クロージャと高階関数、オブジェクトとクラス、エラー設計、正規表現を学ぶ全 36 レッスン(665 分)のコースです。ローカルの作品データを題材に、表示とデータを分け、絞り込み・並び替え・入力検証までを組み立てます。Promise、fetch、API 通信、モジュールは次のコースで扱います。

1
土台をそろえる
01. このコースで育てるもの15分
02. strict mode が先に教えてくれる間違い15分
03. 表示とデータを切り分ける20分
04. 第1章まとめクイズ10分
2
配列をパイプラインで扱う
01. map で形を変える20分
02. filter と find で絞り込む20分
03. reduce でひとつにまとめる20分
04. sort と比較関数20分
05. 分類してまとめる groupBy20分
06. つなげて組み立てる20分
07. つくる 作品一覧の絞り込みと並び替え30分
08. 第2章まとめクイズ10分
3
関数を道具にする
01. クロージャで状態を閉じ込める20分
02. 設定を覚えた関数をつくる20分
03. 関数を返す関数20分
04. 副作用のない関数20分
05. 第3章まとめクイズ10分
4
オブジェクトを扱いきる
01. 分割代入で必要な値だけ取り出す20分
02. スプレッドとレストで組み替える20分
03. keys と values と entries20分
04. ビット演算でフラグをまとめる20分
05. 第4章まとめクイズ10分
5
クラスで型をつくる
01. クラスとインスタンス20分
02. private フィールドとアクセサ20分
03. 継承と super20分
04. 多態と static20分
05. つくる 作品コレクションをクラスにする30分
06. 第5章まとめクイズ10分
6
エラーを設計する
01. try catch finally20分
02. 自分でエラーを投げる20分
03. 失敗を画面に出す25分
04. 第6章まとめクイズ10分
7
正規表現
01. 正規表現のきほん20分
02. 入力を検証する20分
03. 置換とキャプチャ20分
04. 第7章まとめクイズ10分

reduce でひとつにまとめる

sum が 1 周ごとに積み上がる
解説

このレッスンで分かること

  • reduce は配列を 1 つの値にたたみ込みます。第 2 引数の初期値は必ず書きます
  • たたむ先は数値でなくてよく、オブジェクトにすれば複数の集計を一度に返せます

合計を出すたびに、外へ let を置いている

入門では合計を for ループで出しました。外に入れ物を用意し、1 件ずつ足していく形です。

JavaScript

const views = [120, 48, 200]; let sum = 0; for (const n of views) { sum += n; } // 368

この「外に用意した入れ物」を引数として持ち歩くのが reduce です。第 1 引数が前回までの結果、第 2 引数が今見ている要素になります。

JavaScript

const total = views.reduce((sum, n) => sum + n, 0); // 368

最後の 0 が初期値です。1 回目の呼び出しでは sum に 0 が、n に先頭の要素が入ります。返した値が次の呼び出しの sum になり、最後の戻り値がそのまま reduce の結果になります。

回sumn返す値
10120120
212048168
3168200368

初期値は省略できますが、省略すると先頭の要素がそのまま初期値になります。この形で空配列を渡すと Reduce of empty array with no initial value で落ちます。初期値は必ず書く、と決めておくと事故がひとつ消えます。

初期値は「何と比べ始めるか」を決めている

初期値は数値に限りません。オブジェクトにすると、集計を複数まとめて持ち歩けます。タグの中でいちばん長い名前を探す例です。

JavaScript

const tags = ["HTML", "CSS", "JavaScript"]; const longest = tags.reduce( (acc, tag) => { return tag.length > acc.length ? { name: tag, length: tag.length } : acc; }, { name: null, length: -1 } ); // { name: "JavaScript", length: 10 }

比べかたを「より大きいとき」にしているのには意図があります。同じ長さが並んだとき、先に出てきたほうを残したいからです。>= にすると、あとから来た同点の要素で上書きされます。

初期値の length を -1 にしているのも同じ理由です。0 にすると、空文字しか無いときに 1 件も選ばれず、name が null のまま返ってしまいます。初期値の仕事は「絶対に負ける値を置いて、1 件目を必ず勝たせる」ことだと考えると決めやすくなります。合計なら 0、件数なら 0、最大なら十分に小さい値です。

解説

acc を書き換えて返す形も動きますが、新しいオブジェクトを返す形にしておくと、初期値のオブジェクトを使い回して結果が混ざる事故が起きません。

どこまで reduce にするか

reduce は何でも書けてしまうため、使いすぎると読みにくくなります。合計や最大や件数のように 1 つの値にまとめるなら reduce、件数を減らすだけなら filter、形を変えるだけなら map です。同じ結果になるなら、読んだ人に何が伝わるかで選びます。

0 件のときに何を返すかも、集計を書くたびに必ず決めます。合計なら 0、代表を選ぶなら null、といった具合です。初期値がそのまま返るように書いておけば、length を見る分岐は要りません。

集計値が数値なのか文字列なのかも 1 つに決めます。toFixed が返すのは文字列なので、そのあとで足し算をすると静かに文字列の連結になります。表示のための整形は、画面に出す直前に 1 か所でやるのが安全です。

よくある間違い

  • コールバックで return を書き忘れる — 次の回の第 1 引数が undefined になり、結果も undefined になります

JavaScript

// undefined が返る views.reduce((sum, n) => { sum + n; }, 0);
  • 引数の順番を取り違える — 第 1 引数が集計中の値、第 2 引数が要素です。acc と sum のように名前を書き分けておくと取り違えにくくなります

要件

  1. 関数名は aggregateViews とし、引数は作品の配列 works を 1 つだけ受け取る
  2. 戻り値は total と count と topTitle の 3 つのキーを持つオブジェクトにする
  3. total は views の合計、count は件数、topTitle は views が最大の作品のタイトルにする
  4. 同じ最大値が複数あるときは先に出てきたほうを選び、空配列のときは total と count を 0、topTitle を null にする

入出力例

aggregateViews([{"id":1,"published":true,"tags":["HTML","CSS"],"title":"プロフィールサイト","views":120,"year":2026},{"id":2,"published":true,"tags":["HTML"],"title":"自己紹介カード","views":48,"year":2026},{"id":3,"published":true,"tags":["HTML","CSS"],"title":"スキル一覧の表","views":32,"year":2025},{"id":4,"published":false,"tags":["JavaScript"],"title":"作品ギャラリー","views":8,"year":2025},{"id":5,"published":true,"tags":["JavaScript"],"title":"学習ログ","views":200,"year":2024}]) → {"count":5,"topTitle":"学習ログ","total":408} aggregateViews([{"id":1,"published":true,"tags":["HTML","CSS"],"title":"プロフィールサイト","views":120,"year":2026}]) → {"count":1,"topTitle":"プロフィールサイト","total":120} aggregateViews([{"id":4,"published":false,"tags":[],"title":"作品ギャラリー","views":0,"year":2025},{"id":5,"published":true,"tags":[],"title":"学習ログ","views":0,"year":2024}]) → {"count":2,"topTitle":"作品ギャラリー","total":0} aggregateViews([]) → {"count":0,"topTitle":null,"total":0}

ヒント

初期値をオブジェクトにすると、合計と件数と最大を 1 回の走査でまとめられます。

最大を覚えておくために、戻り値には出さない作業用のキーを初期値に足しておくと書きやすくなります。

表示回数が 0 の作品しか無い場合も topTitle が決まるよう、作業用の初期値は 0 ではなく -1 のように小さい値にします。

生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/03/27·更新 2026/08/26

関連レッスン

  • sort と比較関数

    sort が元の配列を並べ替えて壊してしまう点と、比較関数を省くと数値が文字列として比べられる点を押さえます。複製してから並べ替える書き方を身につけます。

  • 分類してまとめる groupBy

    配列の要素をキーごとのまとまりに分ける書き方を学びます。reduce の初期値を空オブジェクトにして、年ごとに作品を束ねます。

  • つなげて組み立てる

    filter と sort と map を 1 本の流れにつないで表示用のデータを組み立てます。つなぐ順番で結果も計算量も変わることを確かめます。

  • つくる 作品一覧の絞り込みと並び替え

    この章で学んだ map と filter と reduce と sort と分類をすべて使い、作品一覧の表示データを 1 本の関数にまとめます。絞り込みの条件はオブジェクトで受け取ります。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • 配列サイズ固定の同型データの集まり
  • 引数位置引数=順番で渡す。
  • オブジェクトキーと値のペアで構造を作るデータ
  • ループ繰り返し処理。矢印で戻すか専用記号で示す
  • 戻り値呼び出し元への返答を表す点線矢印
  • コールバック子から親へ通知するための関数 props
  • 関数処理に名前を付けて再利用できる単位
main.js
学習モード
エディタを読み込んでいます

メモ

reduce でひとつにまとめる

⌘S で保存