更新日:
【JavaScript】 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
となります。そのため、最初に0
がaccumulator
に代入されます。それに対して、配列の最初の要素である1
が足され、返り値として0
+1
の1
が返されます。
次のループでは、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倍にした新しい配列を作成する例です。
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のように使える
reduce
は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メソッドは配列の各要素に対して特定の処理を実行し、最終的に一つの値を返すメソッド
- 配列のメソッドの中でも非常に万能な働きをする
- 予期せぬ結果にならないよう初期値は必ずセットすることを推奨