お知らせ

【JavaScript】【初心者向け】reduce()の使い方やメリット・デメリットについて解説

JavaScript

どうも、こんにちは!ピコっそです。

普段からJavaScriptの学習をしているのですが、最近とくに便利だと感じているメソッドがあります。
それが―― reduce() です!

一見むずかしそうに見えますが、使い方を理解すればコードを短く、そしてスマートに書けるようになります。
今回はそんな reduce()の基本的な使い方や仕組み、メリット・デメリット をわかりやすく解説していきます。

「for文ばかり使っている」「mapやfilterはわかるけどreduceは苦手」という方も、
この記事を読めばきっと使いこなせるようになりますよ。
ぜひ最後まで読んでみてください!

reduce()とは

reduce()とはずばり、

配列の全要素を1つの結果にまとめるための配列メソッド

になります。

例えば、配列 [1, 2, 3, 4] があるとき、合計値を出すには普通 for文 でループしますが、reduceを使えばたった1行で書けます👇

const nums = [1, 2, 3, 4];
const total = nums.reduce((acc, cur) => acc + cur, 0);
console.log(total); // 10

またこれをfor文で書く場合は、

const nums = [1, 2, 3, 4];
let total = 0;
nums.forEach(n => {
    total += n;
});
console.log(total);

このようになり、コードが冗長になります。

基本構文は以下のとおりです。

array.reduce((accumulator, currentValue) => {
    // 処理内容
    return accumulator;
}, 初期値);

ポイント
・accumulator(累積値)…これまでの合計・結果を保持する

・currentValue(現在の値)…今処理している要素

・初期値…最初のaccumulatorに代入する値(多くは0)

このように、reduce()はfor文やforEach関数を置き換える強力な関数で、使いこなせると「合計」「平均」「カウント」「グルーピング」など何でも書ける「配列処理の最終兵器」だと私は考えております。

reduceの主な使い道

reduce() はとても応用範囲が広く、「合計」「平均」「カウント」「グルーピング」など、
さまざまな集計処理をたった1行で実現できる非常に便利なメソッドです。

以下では、主な使用例をいくつか紹介します👇
ぜひ実際に動かしながら理解してみてください。

合計の算出

まず、reduce()を使い合計を算出するコード例を挙げます。個人的に、この使い方が一番メジャーだと考えております。

//配列
const scores = [80, 90, 75, 100, 65];

//配列scoresのデータをreduceを使って合計をtotalにまとめる
const total = scores.reduce((acc,current) =>{
    return acc + current;
},0)

//totalを出力
console.log(total);

ポイント
・scores の要素を 1つずつ current に渡して、acc に加算していく

・acc(累積値)の結果を total に代入

・最終的に total を出力すれば合計が求まる

平均の算出

続いて、reduce()を使って平均値を求める方法を紹介します。
このパターンは「合計」を応用したシンプルな例で、よく使われます。

//配列
const scores = [80, 90, 75, 100, 65];

//reduce()を使って合計を算出し、変数maxに代入
const max = scores.reduce((acc,current) =>{
    return acc + current;
},0)

//平均値を求める変数aveを用意        
let ave = 0;

// 変数 max から配列 scores の要素数 (scores.length) で割る
ave = max / scores.length;

// 結果を出力
console.log(ave);//82

ポイント
・reduce()で配列scoresの合計を算出し、maxに代入

・合計値をscores.length(要素数)で割り、aveに代入

・最終的にaveを出力して平均値を表示

最大値の算出

続いて、reduce()を使って、最大値の算出方法もコードと解説を載せておきます。reduce()を使った最大値の算出方法もよく使うので覚えておくと便利になります。

//配列
const nums = [12, 45, 22, 89, 34];

//reduce()を使い、配列numsのデータをそれぞれcurrentに代入
const max_value = nums.reduce((acc,current) => {
    //accよりcurrentの方が大きい場合に限り、accの数値をcurrentに更新
    if(acc < current){
        acc = current;
    }
    return acc;
},0)

//最終的な結果を出力
console.log(max_value);//89

ポイント
・reduceを使い、配列内の各データをcurrentに代入

・accとcurrentの数値の大きさを比較し、currentの方が大きい場合に限り更新

・更新したデータを定数max_valueに代入し、出力

・補足
・この処理は「常に一番大きい値だけを保持」していくため、最終的に配列中の最大値を求めることができます。

・負の数を扱う場合は初期値を nums[0] にしておくのが安全です。

文字列の出力

reduce()を使うと数値の計算だけでなく、文字列の処理にも応用することができます。

文字列を順番に結合していく場合、for文よりもスッキリ書けるのがポイントです。

//配列
const words = ["I", "love", "JavaScript"];

//配列内の各ワードをcurrentに格納し、accにそれぞれ代入(空白文字も込)
const word_total = words.reduce((acc, current) =>{
    return acc +' '+ current;
}, "")

//結果を出力
console.log(word_total);// I love JavaScript

ポイント
・文字の配列もreduce()を使えば、数値と同じくcurrentに代入可能!

・currentをaccに組み込んで、文字列をどんどん連結していく

・最終的に完成した文字列をword_totalに代入して出力

・補足
・この処理は実際には「単語を一文にまとめる」という操作。
・たとえばチャットメッセージの結合やログ整形などでも使われます。

単語の出現回数をカウント(応用)

reduce()を使えば、配列内にある同じ単語がどれくらい出てきたかをカウントすることもできます。これは応用編の内容なので、完全に理解できなくても大丈夫です。
(ちなみに私も最初はAIに助けてもらいました💦)

// 配列:各フルーツ名が入っている
const fruits = ["apple", "banana", "apple", "orange", "banana", "apple"];

// reduce()を使って出現回数を集計する
const count = fruits.reduce((acc, cur) => {
  // acc:累積結果を保持するオブジェクト(最初は {} )
    // cur:現在処理している要素(例: "apple", "banana")

    // acc[cur] は「オブジェクト acc の中のキー名 cur」
    // 例: cur = "apple" のとき、 acc["apple"]

    // (acc[cur] || 0)
    // → まだキーが存在しない場合は undefined なので 0 を使う
    // → すでにキーがある場合はその値(出現回数)を使う
    // → 最後に +1 してカウントを増やす
  acc[cur] = (acc[cur] || 0) + 1;

  // ここで更新した acc を返す(次のループで使うため)
    return acc;
}, {});// 初期値は空のオブジェクト {}(ここに集計結果を貯める)

// reduceがすべての要素を処理し終えると、acc には
// { apple: 3, banana: 2, orange: 1 } が入っている
console.log(count); // { apple: 3, banana: 2, orange: 1 }

なおこのコードはChatGPTに解説してもらいました

ポイント
・acc(累積オブジェクト)を使って結果を蓄積する

・acc[cur] = (acc[cur] || 0) + 1 でカウント処理を実現

・reduce() は配列を「1つの結果(オブジェクト)」にまとめるメソッド

・補足
・reduceを使えば、配列の集計やグルーピングも同じ考え方で実現できます。
・ここは慣れるまで少し時間がかかる部分なので、焦らず実際にコードを動かしながら理解していけばOKです!(チャットGPTより)

reduce()を使うメリット

reduce()を使うメリットについて解説します。

ここでは、実際に使って感じたreduce()のメリットを3つ紹介します。

コードを短く・読みやすくできる

reduce()を使うと、複雑なループ処理をたった1行でまとめられるのが大きな強みです。
たとえば「配列の合計」や「最大値の取得」などを、for文やforEachよりもスッキリ書けます。
(個人的には一番感動したところです)

// for文
let sum = 0;
for(let i = 0; i < nums.length; i++) {
    sum += nums[i];
}

// reduce
const sum = nums.reduce((a, b) => a + b, 0);

👉可読性が高く、エラーも減るのがポイントです。

配列から“どんな結果”にも変換できる自由度の高さ

reduce()は配列を1つの値にまとめる関数ですが、その1つの値は数値・文字列・オブジェクト・配列など何でもOKです。

つまり、
• 合計(数値)
• 文字列の連結
• オブジェクトへの集計(出現回数など)
• 新しい配列や構造の作成

など、自由自在に変換できるのが大きなメリットです。(個人的には文字列を処理するreduce()構文は少し難しいので注意

他の配列メソッドと組み合わせて強力になる

map()filter()などと組み合わせると、より複雑な処理も一気に書けます。
これにより、「データ整形 → 絞り込み → 集計」のような処理を1つの流れで完結できます。

const users = [
    { name: "A", age: 25 },
    { name: "B", age: 30 },
    { name: "C", age: 20 }
];

const average = users
    .filter(user => user.age >= 20)
    .reduce((acc, user) => acc + user.age, 0) / users.length;

console.log(average);

👉 複数のメソッドを組み合わせても、コードがシンプルで見通しがよくなるのが特徴です。

このように、reduce()の最大のメリットは「自由度の高さ × コードのシンプルさ」であると考えます。ただし、reduce()を使った文字列の処理は少し難易度が高いので、練習して慣れる必要があります。

reduce()を使うデメリット

reduce()を使うデメリットについても解説します。

ここでは、実際に使って感じたreduce()のメリットを3つ紹介します。

可読性が下がりやすい(特に初心者には難しい)

reduce()は一見シンプルですが、
「acc(累積値)」「cur(現在の値)」「初期値」などの概念が絡むため、
慣れていない人には「何をしているのかわかりにくい」という欠点があります。

// 一見短いが、初心者には意味がわかりづらい
const sum = nums.reduce((a, b) => a + b, 0);

👉 「1行で書ける=わかりやすい」ではない点に注意。
チーム開発や他人に見せるコードでは、
あえてfor文を使った方が伝わりやすい場合もあります。

私個人としては、初めてこのコードを見る人がいたら、コメントアウトで説明してあげるのも一つの対策だと思います。

ネストが増えると処理の見通しが悪くなる

reduce()の中でさらに条件分岐他の配列メソッドを使うと、一気に読みにくくなるという落とし穴があります。

// NG例:reduceの中にifとオブジェクト処理が混在
const result = items.reduce((acc, cur) => {
  if (cur.type === "fruit") {
    acc[cur.name] = (acc[cur.name] || 0) + cur.count;
  }
  return acc;
}, {});

👉 ロジックが複雑化するほど「普通のfor文の方が見やすい」ケースも。
シンプルにまとめられない時は、reduceを無理に使わない判断も大事です。

reduceを使った文字列の処理が難しいと私が感じる理由はここにあるかもしれません。

初期値を間違えるとエラーや想定外の動作を起こす

reduce()では、最後の引数の初期値が非常に重要です。
初期値を省略したり、型を間違えるとバグの原因になります。

// 初期値を省略した場合(最初の要素がaccになる)
const wrong = [1, 2, 3].reduce((a, b) => a + b); 
// OKだが、空配列だとエラーになる!

// 安全な書き方
const safe = [1, 2, 3].reduce((a, b) => a + b, 0);

👉 初期値を正しく設定しないと、
空配列でエラーになったり、想定外の型(文字列やオブジェクト)になったりするので注意!

個人的には配列を「どのようにしてまとめたいか」を意識すると意外とこの問題は解消しました

reduce()は強力ですが、「使う場面を選ぶ」ことが大切。シンプルな処理ならfor文、複雑な集計ならreduce、というように目的に応じて使い分けるのが上級者の使い方です。

まとめ

今回はJavaScriptでreduce()の使い方について解説しました。

reduce()は配列の全要素を1つの結果にまとめるための配列メソッドで数値だけでなく、文字列を格納した配列も対応していることから、難しいが使い方を覚えれば汎用性が高いメソッドである印象を持ちました。

reduce()を使ったメリット・デメリットは以下のとおりです。

メリットデメリット
コードを短く・読みやすくできる可読性が下がりやすい
自由度の高さネストが増えると処理の見通しが悪くなる
他の配列メソッドと組み合わせて強力になる初期値を間違えるとエラーや想定外の動作を起こす

上記の通りとなります。

reduce()は最初こそ難しく感じますが、考え方を理解すれば本当に便利なメソッドです。
「必要な時に使えるようになる」ことを目標に、少しずつ慣れていくのがベストだと思います。

最後に

今回は非常に長い記事となりました。最後まで読んでいただき本当にありがとうございました。

今回の記事は少し難易度が高かったのですがreduceの使い方を少しでも理解できた方がいれば嬉しい限りです。

ブログ活動のほかにもXでプログラミングの記事や情報を発信していますので、ぜひフォローの方、よろしくお願いいたします。

https://twitter.com/pikosso1268?s=21

では最後までご覧いただき、ありがとうございました。

今後も初心者でも理解しやすいJavaScript・PHPの基礎シリーズを投稿していきます!

どうぞよろしくお願いいたします。

コメント

タイトルとURLをコピーしました