reduce

生田 陸人
LuaGate エンジニア / 現役エンジニア
編集 LuaGate編集部

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

  • reduce((acc, cur) => ..., initial) で配列を 1 つの値に集約
  • acc は累積値、cur は現在要素、initial は初期値 (省略可だが空配列で落ちる)
  • 合計、最大、グルーピング、オブジェクト化など何でも作れる万能ツール
  • map + filter + reduce の 3 段で並ぶ場面では reduce 1 つにまとめられる

reduce とは

配列を1つの値に集約するreduceの使い方をマスターしよう。本レッスンでは、reduce の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

reduce

配列の全要素を1つの値に集約する強力なメソッドです。

基本的な使い方

JavaScript

const sum = [1, 2, 3, 4].reduce((acc, cur) => acc + cur, 0); // 0 + 1 = 1 → 1 + 2 = 3 → 3 + 3 = 6 → 6 + 4 = 10

オブジェクトに集約

JavaScript

const items = ["apple", "banana", "apple"]; const counts = items.reduce((acc, item) => { acc[item] = (acc[item] || 0) + 1; return acc; }, {}); // { apple: 2, banana: 1 }

reduceはアキュムレータ(acc)の初期値と更新ロジックが重要です。この問題では、学生の成績をreduceで集計しましょう。

実務で遭遇するパターン

中級レッスンで学んだことが、実際の業務コードでどう登場するかを整理します。

  • 合計 / 平均nums.reduce((s, n) => s + n, 0)
  • グルーピングitems.reduce((acc, x) => { (acc[x.cat] ??= []).push(x); return acc }, {})
  • カウントwords.reduce((m, w) => ({ ...m, [w]: (m[w] || 0) + 1 }), {})
  • 配列をオブジェクトに変換users.reduce((m, u) => { m[u.id] = u; return m }, {})

コードレビューで指摘されがちなポイント

PR を出すとシニアから入りやすい指摘です。先回りで身につけておけばレビューが一発で通ります。

  • 初期値 (initial) を省略 ─ 空配列で TypeError、必ず初期値を渡す
  • acc を mutateacc.push(...) は副作用あり、不変派は [...acc, ...]
  • reduce で書けるのに for / 逆に for のほうが読みやすいのに reduce ─ 場面で選ぶ
  • ネストが深い reduce ─ ヘルパー関数に切り出すと読みやすい

パフォーマンス考慮事項

  • 1 パスで完了filter + map + reducereduce 1 つにまとめると速い
  • { ...acc, ... } のスプレッド ─ 大きいオブジェクトでは毎回コピーになり遅い、mutate のほうが速い
  • for ループのほうが速いことも ─ ホットパスでは for + 累積変数
  • 並列化不可reduce は順序依存、並列が欲しい場面は別途設計
この章のポイント

ここまでの要点 reduce は配列を 1 値に集約、初期値必須、map+filter+reduce を 1 つにまとめられる万能ツール。スプレッドの累積はメモリ注意。

よくある質問

Q. reduce はどんなときに使うべきですか?

A. 合計・最大値・グルーピングなど、配列を 1 つの値や別の構造にまとめたいときに有効です。単純な合計なら sum / Array.prototype.reduce((a,b)=>a+b,0) で OK ですが、複雑なロジックでは for ループの方が読みやすいこともあります。

Q. 初期値は省略しても良いですか?

A. 省略すると配列の先頭要素が初期値になり、空配列のときに TypeError になります。明示的に 0 や [] を渡しておくと安全で、型推論にも優しくなります。可読性と安全性の両面から初期値は付ける派が多数です。

Q. reduce でオブジェクトを作るには?

A. items.reduce((acc, x) => ({ ...acc, [x.id]: x }), {}) のように初期値に {} を渡し、各反復で展開構文を使います。要素数が多い場合は scatter で性能劣化するため、acc[x.id] = x; return acc; のように mutate する形も検討してください。

次のレッスン

次は sort と メソッドチェーン で、配列の並び替えとメソッドチェーンを学びます。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. reduce の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. reduce とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

入出力例

test-cases.txt

summarizeScores([{"name":"太郎","score":80},{"name":"花子","score":90},{"name":"次郎","score":70}]){"average":80,"count":3,"highest":90,"total":240} summarizeScores([{"name":"Alice","score":100}]){"average":100,"count":1,"highest":100,"total":100} summarizeScores([{"name":"A","score":65},{"name":"B","score":78},{"name":"C","score":92},{"name":"D","score":55}]){"average":72.5,"count":4,"highest":92,"total":290}
main.js
main.js
学習モード

メモ

reduce

⌘S で保存