実際には、受け入れられた回答はあなたを変えています。
http://elijahmanor.com/reducing-filter-and-map-down-to-reduce/
しかし、私はちょうどリンクを入れないで、ここでのショートバージョンがあります:あなたは本当に、ラを減らす使用することにしたいです。
あなたはreduce引数に(通常は匿名の)関数を指定します。
匿名関数は、2つのパラメータ(map/filter/forEachに渡される匿名関数のような)をとるもので、操作対象のiterateeです。しかし、関数呼び出しの間に渡される値はであり、しばしばメモと呼ばれる値であることを意味しています。
Array.filter()は1つの引数(関数)しか取るわけではありませんが、Array.reduce()は重要な(ただしオプションですが)第2引数をとります: 'memo'の初期値匿名関数を最初の引数として使用し、その後、関数呼び出しの間で変更して渡すことができます。(提供されていなければ、最初の匿名関数呼び出しの 'memo'は最初のiterateeになり、 'iteratee'引数は実際に配列の2番目の値になります)
私たちの場合、空の配列を渡して開始し、次にiterateeを配列に挿入するかどうかを関数に基づいて行うかどうかを選択します。これがフィルタリングプロセスです。
最後に、各無名関数呼び出しで 'array in progress'を返し、reduceはその戻り値をとり、引数(memo)として次の関数呼び出しに渡します。
これにより、フィルタとマップを1回の反復で実行できるため、必要な反復回数を半減できます。 :)
詳細については、MDNまたは上記のリンクを参照してください。 :)削減コールの
Basicの例:
let array = [1,2,3];
const initialMemo = [];
array = array.reduce((memo, iteratee) => {
// if condition is our filter
if (iteratee > 1) {
// what happens inside the filter is the map
memo.push(iteratee * 2);
}
// this return value will be passed in as the 'memo' argument
// to the next call of this function, and this function will have
// every element passed into it at some point.
return memo;
}, initialMemo)
console.log(array) // [4,6], equivalent to [(2 * 2), (3 * 2)]
より簡潔版:最初iterateeが1より大きいなかったし、そうで濾過したことを
[1,2,3].reduce((memo, value) => value > 1 ? memo.concat(value * 2) : memo, [])
は注意してください。また、その存在を明確にして注意を引くためにちょうど命名されたinitialMemoに注意してください。再び、それは最初の無名関数呼び出しに「メモ」として渡され、無名関数の戻り値は「メモ」引数として次の関数に渡されます。
メモの古典的な使用例のもう1つの例は、配列内の最小または最大の数値を返すことです。例:
[7,4,1,99,57,2,1,100].reduce((memo, val) => memo > val ? memo : val)
// ^this would return the largest number in the list.
独自のものを作成する方法の例は、機能を減らす(これは多くの場合、私は見つけるこのような理解の機能を助けます):私は徹底的にその実装をテストしていない
test_arr = [];
// we accept an anonymous function, and an optional 'initial memo' value.
test_arr.my_reducer = function(reduceFunc, initialMemo) {
// if we did not pass in a second argument, then our first memo value
// will be whatever is in index zero. (Otherwise, it will
// be that second argument.)
const initialMemoIsIndexZero = arguments.length < 2;
// here we use that logic to set the memo value accordingly.
let memo = initialMemoIsIndexZero ? this[0] : initialMemo;
// here we use that same boolean to decide whether the first
// value we pass in as iteratee is either the first or second
// element
const initialIteratee = initialMemoIsIndexZero ? 1 : 0;
for (var i = initialIteratee; i < this.length; i++) {
// memo is either the argument passed in above, or the
// first item in the list. initialIteratee is either the
// first item in the list, or the second item in the list.
memo = reduceFunc(memo, this[i]);
}
// after we've compressed the array into a single value,
// we return it.
return memo;
}
、とだけ私の頭の上からそれを書きましたが、私の2つの基本的なテストケースではうまくいくようでした。実際の実装では、例えば索引のようなものにアクセスすることができますが、これがその要点を複雑ではないと感じるのを助けてくれることを願っています。
マップ 'と反復を倍増するのではなく、' reduce'を使用することを検討してください - >フィルタ '。私は、この質問に来る人々が答えを見ずに間違ってこれを読んで、最終的にはより良い方法があることを学ぶことを心配しています。 –
なぜ2回の反復が1回最悪であるのかを詳しく説明できますか?つまり、2 * O(n)は私にはO(2 * n)に相当します... –
はい、20 * 2と10 * 4は同じです...しかし、同じ数の操作フィルタ/マップ関数内で実行される場合、関数呼び出しの数を倍にしてそのようにすることができます。フィルタ(f) - >マップ(g)対縮小(h)。すべての関数呼び出しにはコストがかかります。 (はい、一般的に無視しても構いませんが、map/filter/reduceは非常に大きなリストで使用される関数の型です。 私はあとでいくつかのjsperfテストを実行して、その時点で私の答えとこのコメントを説明(検証)して更新しようとします。 (それ以外は、これを減らすための理想的なユースケースです) –