reduce は配列の「すべての要素を一つの値にまとめる(還元する)」ためのメソッドです。
たとえば「配列の合計」「平均」「要素の出現回数を数える」「配列を平坦化(ネスト解除)」などに使います。
1. 基本イメージ(超カンタン)
配列の要素を左から順に見ていき、「累積(これまでの合計など)」 を更新していく。
毎回コールバック関数が呼ばれ、その戻り値が次回の累積値になります。最後に累積値を返すのが reduce です。
構文(見やすく)
配列.reduce(function(accumulator, currentValue, index, array) {
// accumulator: これまでの「累積」値
// currentValue: 今見ている要素
// index: 今のインデックス(省略可)
// array: 元の配列(省略可)
return 新しい累積値;
}, 初期値 /*省略可だが指定推奨*/);
JavaScript2. まずは一番わかりやすい例:数値の合計
const nums = [48, 75, 92, 61, 54, 83, 76];
const total = nums.reduce(function(sum, n) {
return sum + n;
}, 0);
console.log(total); // 489
JavaScriptポイント:
sumが累積値(最初は0に設定)nが現在の要素- 毎回
sum + nを返して次のsumにする
手で追うとこんな感じ(各ステップ)
初期値 sum = 0
1回目: sum=0, n=48 → return 48 → sum becomes 48
2回目: sum=48, n=75 → return 123 → sum becomes 123
… 最終的に 489
3. 初期値はなぜ指定するのか?
初期値を指定しないと最初の accumulator が配列の最初の要素になります(空配列だとエラー)。
混在データや空配列を扱う場合は必ず初期値を指定するのが安全です。
例:空配列で初期値がないとエラーになるケース
[].reduce((a,b) => a + b); // TypeError: Reduce of empty array with no initial value
JavaScript4. オブジェクトの配列で特定フィールドの合計を出す
const users = [
{name: 'Yamada', score: 75},
{name: 'Suzuki', score: 91},
{name: 'Kudou', score: 80}
];
const sumScores = users.reduce((acc, user) => acc + user.score, 0);
console.log(sumScores); // 246
JavaScriptポイント:user.score のように合計したいプロパティを指定します。
5. 平均を出す(合計→平均)
const nums = [10, 20, 30, 40];
const total = nums.reduce((acc, n) => acc + n, 0);
const avg = total / nums.length;
console.log(avg); // 25
JavaScriptreduce で合計を取り、そのあと length で割るのが普通です。
(別案:reduce の中で count と sum を同時に保持することも可能)
6. 発生回数(出現数)を数える例
たとえば "apple", "banana", "apple" のような配列でそれぞれのアイテムの出現回数を得るとき:
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana'];
const counts = fruits.reduce((acc, f) => {
if (!acc[f]) acc[f] = 0;
acc[f] += 1;
return acc;
}, {});
console.log(counts); // { apple: 2, banana: 2, orange: 1 }
JavaScriptここでの初期値は 空オブジェクト {} 。acc にプロパティを増やしながらまとめます。
7. ネストした配列を平坦化(1段階だけ)
配列の中に配列がある場合、それらをまとめて一つの配列にする例:
const nested = [[1,2], [3,4], [5,6]];
const flat = nested.reduce((acc, arr) => acc.concat(arr), []);
console.log(flat); // [1,2,3,4,5,6]
JavaScriptacc.concat(arr) で配列を結合しています。最近は flat() もあるので単純ならそちらが楽です。
8. 注意点とよくある間違い
- 初期値を忘れると空配列でエラーや、最初の値が想定外になることがある。明示的に初期値を与えよう。
reduceのコールバックは不変(副作用を作らない)ようにするのが理想。例外的にオブジェクトを直接変えるやり方をするとバグを生みやすい。- 可読性を意識する:単純な合計なら
forよりreduceの方が短いが、複雑な処理だと読みづらくなることもある。チームの慣習を考えて使おう。
9. よく使う短い書き方(アロー関数)
const total = [1,2,3,4].reduce((s, n) => s + n, 0);
JavaScript10. 練習問題
- 配列
[3, 7, 2, 9, 5]の合計をreduceで求めよ。 - オブジェクト配列
[{a:2},{a:3},{a:5}]のaを合計せよ。 - 単語配列
['dog','cat','dog','bird']の出現回数オブジェクト(例{dog:2, cat:1, bird:1})を作れ。 - 配列
[[1],[2,3],[4,5,6]]をフラットに(一つの配列)しなさい。
11. 解答
[3,7,2,9,5].reduce((a,b) => a + b, 0); // 26
JavaScript[{a:2},{a:3},{a:5}].reduce((acc, obj) => acc + obj.a, 0); // 10
JavaScript['dog','cat','dog','bird'].reduce((acc, w) => {
acc[w] = (acc[w] || 0) + 1;
return acc;
}, {}); // {dog:2, cat:1, bird:1}
JavaScript[[1],[2,3],[4,5,6]].reduce((acc, arr) => acc.concat(arr), []); // [1,2,3,4,5,6]
JavaScript