From 4da0f19428ca8a2146b262bc974137f8864eb74b Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Thu, 20 Jan 2022 01:10:59 +0900 Subject: 2021/12/10 時点の英語版に同期 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reference/global_objects/array/reduce/index.md | 317 +++++++++++---------- 1 file changed, 165 insertions(+), 152 deletions(-) (limited to 'files/ja/web') diff --git a/files/ja/web/javascript/reference/global_objects/array/reduce/index.md b/files/ja/web/javascript/reference/global_objects/array/reduce/index.md index ec1f646903..29c5f6b03e 100644 --- a/files/ja/web/javascript/reference/global_objects/array/reduce/index.md +++ b/files/ja/web/javascript/reference/global_objects/array/reduce/index.md @@ -16,47 +16,54 @@ translation_of: Web/JavaScript/Reference/Global_Objects/Array/reduce --- {{JSRef}} -**`reduce()`** メソッドは、配列のそれぞれの要素に対してユーザーが提供した「縮小」コールバック関数を呼び出します。その際、直前の要素における計算結果の返値を渡します。配列のすべての要素に対して縮小関数を実行した結果が単一の値が最終結果になります。 +**`reduce()`** メソッドは、配列のそれぞれの要素に対して、順番通りに、ユーザーが提供した「縮小」コールバック関数を呼び出します。その際、直前の要素における計算結果の返値を渡します。配列のすべての要素に対して縮小関数を実行した結果が単一の値が最終結果になります。 -`reduce()` で一番わかりやすいのは、配列のすべての要素の和を返す場合でしょう。 - -縮小関数は配列を要素ごとに走査し、それぞれの段階で、前の段階の結果に現在の配列の値を加えていきます (この結果は、それ以前のすべての段階を合算したものです)。 +コールバックの初回実行時には「直前の計算の返値」は存在しません。 +初期値が与えらえた場合は、代わりに使用されることがあります。 +そうでない場合は、配列の要素 0 が初期値として使用され、次の要素(0 の位置ではなく 1 の位置)から反復処理が開始されます。 -次のインタラクティブサンプルで紹介します。 +`reduce()` で一番わかりやすいのは、配列のすべての要素の和を返す場合でしょう。 {{EmbedInteractiveExample("pages/js/array-reduce.html")}} +縮小関数は配列を要素ごとに走査し、それぞれの段階で、前の段階の結果に現在の配列の値を加えていきます (この結果は、それ以前のすべての段階を合算したものです)。 + ## 構文 ```js // アロー関数 -reduce((previousValue, currentValue) => { ... } ) -reduce((previousValue, currentValue, currentIndex) => { ... } ) -reduce((previousValue, currentValue, currentIndex, array) => { ... } ) -reduce((previousValue, currentValue, currentIndex, array) => { ... }, initialValue) +reduce((previousValue, currentValue) => { /* ... */ } ) +reduce((previousValue, currentValue, currentIndex) => { /* ... */ } ) +reduce((previousValue, currentValue, currentIndex, array) => { /* ... */ } ) +reduce((previousValue, currentValue, currentIndex, array) => { /* ... */ }, initialValue) // コールバック関数 reduce(callbackFn) reduce(callbackFn, initialValue) // インラインコールバック関数 -reduce(function callbackFn(previousValue, currentValue) { ... }) -reduce(function callbackFn(previousValue, currentValue, currentIndex) { ... }) -reduce(function callbackFn(previousValue, currentValue, currentIndex, array){ ... }) -reduce(function callbackFn(previousValue, currentValue, currentIndex, array) { ... }, initialValue) +reduce(function(previousValue, currentValue) { /* ... */ }) +reduce(function(previousValue, currentValue, currentIndex) { /* ... */ }) +reduce(function(previousValue, currentValue, currentIndex, array) { /* ... */ }) +reduce(function(previousValue, currentValue, currentIndex, array) { /* ... */ }, initialValue) ``` ### 引数 - `callbackFn` - : 4 つの引数を取る「縮小」関数です。 - - *previousValue* (前回の `callbackfn` の呼び出し結果の値) - - *currentValue* (現在の要素の値) - - *currentIndex* (現在の位置) {{optional_inline}} - - *array* (走査する配列) {{optional_inline}} + - `previousValue`: 前回の `callbackFn` の呼び出し結果の値です。 + 初回の呼び出しでは `initalValue` が指定されていた場合はその値、そうでない場合は `array[0]` の値です。 + - `currentValue`: 現在の要素の値です。 + 初回の呼び出しでは `initalValue` が指定された場合は `array[0]` の値であり、そうでない場合は `array[1]` の値です。 + - `currentIndex`: 現在の位置です。 + 初回の呼び出しでは、 `initialValue` が指定された場合は `0`、そうでない場合は `1` です。 + - `array`: 走査する配列です。 - `initialValue` {{optional_inline}} - - : コールバックが初めて呼び出されたときの *previousValue* の初期値です。 `initialValue` が指定された場合は、 *currentValue* も配列の最初の値に初期化されます。 `initialValue` が指定され*なかった*場合、 *previousValue* は配列の最初の値で初期化され、 *currentValue* は配列の 2 番目の値で初期化されます。 + - : コールバックが初めて呼び出されたときの *previousValue* の初期値です。 + `initialValue` が指定された場合は、 `currentValue` も配列の最初の値に初期化されます。 + `initialValue` が指定され*なかった*場合、 `previousValue` は配列の最初の値で初期化され、 `currentValue` は配列の 2 番目の値で初期化されます。 ### 返値 @@ -64,7 +71,9 @@ reduce(function callbackFn(previousValue, currentValue, currentIndex, array) { . ### 例外 -{{jsxref("TypeError")}}: 配列に要素がなく、かつ `initialValue` が提供されなかった場合に発生します。 +- {{jsxref("TypeError")}} + + - : 配列に要素がなく、かつ `initialValue` が提供されなかった場合に発生します。 ## 解説 @@ -110,157 +119,161 @@ const getMax = (a, b) => Math.max(a, b); [ ].reduce(getMax); // TypeError ``` -### reduce() の動作 +### 初期値がない場合の reduce() の動作 -`reduce()` を以下のように使うことを想像してください。 +下記のコードは、初期値がない場合に配列に `reduce()` を呼び出したときに何が起こるかを示します。 ```js -[0, 1, 2, 3, 4].reduce(function(previousValue, currentValue, currentIndex, array) { - return previousValue + currentValue -}) +const array = [15, 16, 17, 18, 19]; + +function reducer(previous, current, index, array) { + const returns = previous + current; + console.log(`previous: ${previous}, current: ${current}, index: ${index}, returns: ${returns}`); + return returns; +} + +array.reduce(reducer); ``` コールバック関数は 4 回呼び出され、各回の引数の内容は以下のようになります。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- callback の反復処理 - - previousValue - - currentValue - - currentIndex - - array - 返値
初回の呼出し011[0, 1, 2, 3, 4]1
2 回目の呼出し122[0, 1, 2, 3, 4]3
3 回目の呼出し333[0, 1, 2, 3, 4]6
4 回目の呼出し644[0, 1, 2, 3, 4]10
+ callback の反復処理 + + previousValue + + currentValue + + currentIndex + + array + 返値
初回の呼出し15161[15, 16, 17, 18, 19]31
2 回目の呼出し31172[15, 16, 17, 18, 19]48
3 回目の呼出し48183[15, 16, 17, 18, 19]66
4 回目の呼出し66194[15, 16, 17, 18, 19]85
-`reduce()` の返値は、コールバック呼び出しの最後の返値である (`10`) となるでしょう。 +`reduce()` の返値は、コールバック呼び出しの最後の返値である (`85`) となるでしょう。 -通常の関数の代わりに{{jsxref("Functions/Arrow_functions", "アロー関数","",1)}}を指定することができます。下記のコードは上記のコードと同じ結果を返します。 -```js -[0, 1, 2, 3, 4].reduce( (previousValue, currentValue, currentIndex, array) => previousValue + currentValue ) -``` +### 初期値がある場合の reduce() の動作 -*initialValue* を `reduce()` の 2 つ目の引数に渡した場合は、結果は次のようになります。 +ここでは、同じアルゴリズムで同じ配列を減らしますが、 `reduce()` の 2 番目の引数として `10` という*初期値*を渡します。 +``` ```js -[0, 1, 2, 3, 4].reduce((previousValue, currentValue, currentIndex, array) => { - return previousValue + currentValue -}, 10) +[15, 16, 17, 18, 19].reduce( (previousValue, currentValue, currentIndex, array) => previousValue + currentValue, 10 ) ``` +コールバックは 5 回呼び出され、それぞれの呼び出しにおける引数と返値値は次のようになる。 + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- callback の反復処理 - - previousValue - - currentValue - - currentIndex - - array - 返値
初回の呼出し1000[0, 1, 2, 3, 4]10
2 回目の呼出し1011[0, 1, 2, 3, 4]11
3 回目の呼出し1122[0, 1, 2, 3, 4]13
4 回目の呼出し1333[0, 1, 2, 3, 4]16
5 回目の呼出し1644[0, 1, 2, 3, 4]20
+ callback の反復処理 + + previousValue + + currentValue + + currentIndex + + array + 返値
初回の呼出し10150[15, 16, 17, 18, 19]25
2 回目の呼出し25161[15, 16, 17, 18, 19]41
3 回目の呼出し41172[15, 16, 17, 18, 19]58
4 回目の呼出し58183[15, 16, 17, 18, 19]76
5 回目の呼出し76194[15, 16, 17, 18, 19]95
-この場合の `reduce()` の返値は `20` となります。

+この場合の `reduce()` の返値は `20` となります。 ## 例 @@ -427,7 +440,7 @@ console.log(myArrayWithNoDuplicates) ### .filter().map() を .reduce() で置き換える -{{jsxref("Array.filter()")}} を使用した後で {{jsxref("Array.map()")}} を使用すると配列を二度走査しますが、{{jsxref("Array.reduce()")}} では同じ効果を一度の操作で実現することができ、もっと効率的です。(for ループが好きなのであれば、{{jsxref("Array.forEach()")}} で一度の操作で filter と map を行うことができます)。 +{{jsxref("Array.filter()")}} を使用した後で {{jsxref("Array.map()")}} を使用すると配列を二度走査しますが、{{jsxref("Array.reduce()")}} では同じ効果を一度の操作で実現することができ、もっと効率的です。(`for` ループが好きなのであれば、{{jsxref("Array.forEach()")}} で一度の操作で filter と map を行うことができます)。 ```js const numbers = [-5, 6, 2, 0,]; @@ -524,7 +537,7 @@ multiply24(10) // 240 if (!Array.prototype.mapUsingReduce) { Array.prototype.mapUsingReduce = function(callback, initialValue) { return this.reduce(function(mappedArray, currentValue, currentIndex, array) { - mappedArray[index] = callback.call(initialValue, currentValue, currentIndex, array) + mappedArray[currentIndex] = callback.call(initialValue, currentValue, currentIndex, array) return mappedArray }, []) } -- cgit v1.2.3-54-g00ecf