すでにメンバーの場合は

無料会員登録

GitHubアカウントで登録 Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

登録がまだの方はこちらから

Pikawakaにログイン

GitHubアカウントでログイン Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

JavaScript

【JavaScript】 reduceメソッドについて徹底解説!

ぴっかちゃん
ぴっかちゃん

reduceメソッドは配列の各要素に対して特定の処理を実行し、最終的に一つの値を返すメソッドです。

reduceメソッドの基本構文
1
2
3
配列.reduce(function(前回の結果, 各要素) {
  何らかの処理
}, 初期値);

reduceメソッドの基礎情報

この章では、reduceメソッドの基礎情報について解説します。

reduceメソッドの基本的な使い方

reduceメソッドは、配列に対して使用するメソッドです。このメソッドを使うと、配列の各要素を順番に取り出し、コールバック関数で指定された処理を実行し、最終的には一つの値を返します。

以下が基本的な書き方です。

基本的な書き方
1
配列.reduce(コールバック関数, 初期値);

わかりやすく書くと以下のようになります。

基本的な書き方
1
2
3
配列.reduce(function(前回の結果, 各要素) {
  何らかの処理
}, 初期値);

またはアロー関数を使用して以下のように書くこともできます。

基本的な書き方
1
2
3
配列.reduce((前回の結果, 各要素) => {
  何らかの処理
}, 初期値);

「前回の結果」には前回の呼び出しから返された値が入ります。
最初の呼び出し時には前回の結果はないため、「初期値」で設定した値が入ります。
「初期値」は省略することもできますが、省略時には配列の最初の要素が自動で入ります。
「各要素」には配列内の要素が順番に代入されます。

これではわかりにくいので、実際の例を見てみましょう。
次の例では、配列の要素の合計を計算しています。

配列の合計を求める例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const numbers = [1, 2, 3, 4, 5];

const sum = numbers.reduce((accumulator, currentValue) => {
  console.log(`accumulator: ${accumulator}, currentValue: ${currentValue}`)
  return accumulator + currentValue;
}, 0);

console.log(sum);

// 出力:
// accumulator: 0, currentValue: 1
// accumulator: 1, currentValue: 2
// accumulator: 3, currentValue: 3
// accumulator: 6, currentValue: 4
// accumulator: 10 currentValue: 5
// 15

この例のコールバック関数は、前回の結果に各要素を足していくものです。今回はreduceメソッドの第2引数に0を渡しているので、初期値は0となります。そのため、最初に0accumulatorに代入されます。それに対して、配列の最初の要素である1が足され、返り値として0+11が返されます。

次のループでは、accumulatorには先ほどの返り値である1が入ります。currentValueには配列の2番目の要素である2が代入され、1+2=3となります。次のループではaccumulatorには3が代入されるという流れになります。

結果として、配列の要素の合計値が返り値として返されます。

次は配列内の文字を連結させる例です。

文字の連結
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const strings = ["Hello", " ", "World", "!"];

// 文字列を連結する
const result = strings.reduce((accumulator, currentValue) => {
  console.log(`accumulator: ${accumulator}, currentValue: ${currentValue}`)
  return accumulator + currentValue;
}, "");

console.log(result); 

// 出力:
// accumulator: "", currentValue: "Hello"
// accumulator: "Hello", currentValue:  ""
// accumulator: "Hello ", currentValue: "World"
// accumulator: "Hello World", currentValue: "!"
// "Hello World!"

この例も数値を足していくときと同様に、配列の各要素を順番に連結し、最終的に返り値として返します。
初期値として空の文字列をセットしています。

次は配列の要素の最大値と最小値を取得する例です。

最大値の取得
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const numbers = [10, 20, 30, 40, 50];

console.log('============== Max ==============')
const max = numbers.reduce((accumulator, currentValue) => {
  console.log(`accumulator: ${accumulator}, currentValue: ${currentValue}`)
  return Math.max(accumulator, currentValue);
});

console.log(`最大値: ${max}`);

console.log('============== Min ==============')
const min = numbers.reduce((accumulator, currentValue) => {
  console.log(`accumulator: ${accumulator}, currentValue: ${currentValue}`)
  return Math.min(accumulator, currentValue);
});

console.log(`最小値: ${min}`);

// 出力:
// ============== Max ==============
// accumulator: 10, currentValue: 20
// accumulator: 20, currentValue: 30
// accumulator: 30, currentValue: 40
// accumulator: 40, currentValue: 50
// 最大値: 50
// ============== Min ==============
// accumulator: 10, currentValue: 20
// accumulator: 10, currentValue: 30
// accumulator: 10, currentValue: 40
// accumulator: 10, currentValue: 50
// 最小値: 10

Math.maxは引数で渡された数値の中から最大値を返すメソッドです。逆にMath.minは最小値を返すメソッドです。

使用例
1
2
3
4
5
6
7
console.log(Math.max(1, 3, 5)); // 5
console.log(Math.max(-1, -3, -5)); // -1
console.log(Math.max(10, 20, 40, 30)); // 40

console.log(Math.min(1, 3, 5)); // 1
console.log(Math.min(-1, -3, -5)); // -5
console.log(Math.min(10, 20, 40, 30)); // 10

この例では、初期値が設定されていないため、配列の最初の要素が初期値となります、最初のループでは配列の最初の要素同士が比較され、結果としてその要素が返されます。2番目のループでは、accumulatorに最初の要素である10が代入され、currentValueには配列の2番目の要素である20が代入されます。10より20の方が大きいため、20が返されます。このように、配列の各要素を順番に比較していくことで、最大値が最終的な返り値となります。最小値も同じような動きです。

reduceメソッドの応用的な使い方

この章では、reduceメソッドの応用的な使い方について解説します。

オプションで使えるコールバック関数の引数

コールバック関数の引数にはオプションとして2つの引数を使うことができます。

基本的な書き方
1
2
3
配列.reduce(function(前回の結果, 各要素, インデックス, 使用した配列) {
  何らかの処理
}, 初期値);

使わない場合は省略します。
以下がこれらの引数を使ったときの例です。

オプションの引数を使用した例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const cart = [
  { item: 'リンゴ', price: 100, quantity: 3 },
  { item: 'バナナ', price: 50, quantity: 5 },
  { item: 'サクランボ', price: 200, quantity: 2 }
];

const total = cart.reduce((accumulator, currentValue, index, array) => {
  // 商品の小計を累積値に追加
  const itemTotal = currentValue.price * currentValue.quantity;
  console.log(`商品 ${index + 1}/${array.length}: ${currentValue.item}, 小計: ¥${itemTotal}`);
  return accumulator + itemTotal;
}, 0);

console.log(`合計: ¥${total}`);

// 出力:
// 商品 1/3: リンゴ, 小計: ¥300
// 商品 2/3: バナナ, 小計: ¥250
// 商品 3/3: サクランボ, 小計: ¥400
// 合計: ¥950

この例ではcartに入っている商品の合計金額を出力させています。
まずcurrentValue.price * currentValue.quantityで現在の商品の小計を計算します。
出力内容にはindexを使って現在の商品の位置を表示させています。
arrayにはreduceを使っている配列、つまりcartが代入されます。

mapのように使える

reduceを使ってmapのように配列を変換することもできます。
以下は配列内の数値を全て2倍にした新しい配列を作成する例です。

mapのように使える例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const numbers = [1, 2, 3, 4, 5];

const doubledNumbers = numbers.reduce((accumulator, currentValue) => {
  console.log("accumulator:" + ${accumulator} "+ , currentValue: " + ${currentValue})
  accumulator.push(currentValue * 2);
  return accumulator;
}, []);

console.log(doubledNumbers);

// 出力:文字列内の配列が出力される際は[]はつきませんがわかりやすくするためつけています
// accumulator: [], currentValue: 1
// accumulator: [2], currentValue: 2
// accumulator: [2,4], currentValue: 3
// accumulator: [2,4,6], currentValue: 4
// accumulator: [2,4,6,8], currentValue: 5
// [2, 4, 6, 8, 10]

filterのように使える

reducefilterのように配列内の要素をフィルタリングすることもできます。
以下は配列内の要素から偶数のみを抽出する例です。

filterのように使える例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const numbers = [1, 2, 3, 4, 5, 6];

const evenNumbers = numbers.reduce((accumulator, currentValue) => {
  console.log(`accumulator: ${accumulator}, currentValue: ${currentValue}`);
  if (currentValue % 2 === 0) {
    accumulator.push(currentValue);
  }
  return accumulator;
}, []);

console.log(evenNumbers);

// 出力:文字列内の配列が出力される際は[]はつきませんがわかりやすくするためつけています
// accumulator: [], currentValue: 1
// accumulator: [], currentValue: 2
// accumulator: [2], currentValue: 3
// accumulator: [2], currentValue: 4
// accumulator: [2,4], currentValue: 5
// accumulator: [2,4], currentValue: 6
[2, 4, 6]

配列を結合させる

reduceを使って複数の配列を1つの配列にまとめることも可能です。

配列同士の結合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const arrayOfArrays = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];

const flattenedArray = arrayOfArrays.reduce((accumulator, currentValue) => {
  console.log(`accumulator: ${accumulator}, currentValue: ${currentValue}`);
  return accumulator.concat(currentValue);
}, []);

console.log(flattenedArray); 

// 出力:文字列内の配列が出力される際は[]はつきませんがわかりやすくするためつけています
// accumulator: [], currentValue: 1,2,3
// accumulator: [1,2,3], currentValue: 4,5,6
// accumulator: [1,2,3,4,5,6], currentValue: 7,8,9
// [1, 2, 3, 4, 5, 6, 7, 8, 9]

この例ではconcatを使って2つの配列を結合した新しい配列を作成しています。

このようにreduceは配列において非常に万能なメソッドと言えるでしょう。

使う際の注意点

この章ではreduceメソッドを使う際の注意点を紹介します。

繰り返し処理からは抜けられない

reduceメソッドのコールバック関数内ではbreakが使えないため、繰り返し処理から抜け出すことができません。間違って記述するとエラーが発生するので注意しましょう。

エラーが発生するコード
1
2
3
4
5
6
7
8
9
10
const numbers = [1, 2, 3, 4, 5];

const result = numbers.reduce((accumulator, currentValue) => {
  if (currentValue === 3) {
    break; // SyntaxError: Illegal break statement
  }
  return accumulator + currentValue;
}, 0);

console.log(result);

この場合、以下のエラーが発生し、コードが止まります。

エラー文

初期値を指定する重要性

初期値を設定しない場合、reduceは配列の最初の要素を初期値として使用します。ただ、空の配列を処理する場合に初期値を設定していないとエラーが発生します。このような意図しないバグを防ぐためにも初期値を設定することが推奨されます。

初期値を設定しない場合
1
2
3
4
5
6
7
const emptyArray = [];

const sum = emptyArray.reduce((accumulator, currentValue) => {
  return accumulator + currentValue;
});

console.log(sum);

この場合、以下のエラーが発生し、コードが止まります。

エラー文

返り値の型に注意する

reduceは累積値を返すため、コールバック関数の累積値(accumulator)と初期値(initialValue)の型が一致していないと意図しない結果になります。

型の間違い
1
2
3
4
5
6
7
const numbers = [1, 2, 3, 4, 5];

const sum = numbers.reduce((accumulator, currentValue) => {
    return accumulator + currentValue;
}, '0');

console.log(sum); // 出力: "012345"

この例では配列内の要素が数値なのに対し、初期値として文字列の0をセットしてしまっています。
この場合、文字列と数値を連結することになるため返り値の型は文字列になり、結果として012345という文字列が返ってきてしまいました。

この記事のまとめ

  • reduceメソッドは配列の各要素に対して特定の処理を実行し、最終的に一つの値を返すメソッド
  • 配列のメソッドの中でも非常に万能な働きをする
  • 予期せぬ結果にならないよう初期値は必ずセットすることを推奨