指摘されたことを形式化するために、リデューサーは、偶然に同じ型である可能性のある2つの引数を取り、最初の引数に一致する型を返すカタモルフィズムです。
function reducer (accumulator: X, currentValue: Y): X { }
つまり、レデューサーの本体は、currentValue
の現在の値をaccumulator
新しい の値に変換する必要がありますaccumulator
。
アキュムレータと要素の値は両方ともたまたま同じ型である (ただし目的は異なる) ため、これは加算時に簡単に機能します。
[1, 2, 3].reduce((x, y) => x + y);
これらはすべて数値であるため、これは機能します。
[{ age: 5 }, { age: 2 }, { age: 8 }]
.reduce((total, thing) => total + thing.age, 0);
ここで、アグリゲーターに開始値を与えています。ほとんどの場合、開始値は、アグリゲーターが期待するタイプ (最終値として出力されると予想されるタイプ) である必要があります。これを強制されているわけではありません (強制されるべきではありません) が、心に留めておくことが重要です。
それがわかれば、他の n:1 関係の問題に対して意味のある還元を書くことができます。
繰り返される単語の削除:
const skipIfAlreadyFound = (words, word) => words.includes(word)
? words
: words.concat(word);
const deduplicatedWords = aBunchOfWords.reduce(skipIfAlreadyFound, []);
見つかったすべての単語の数を提供する:
const incrementWordCount = (counts, word) => {
counts[word] = (counts[word] || 0) + 1;
return counts;
};
const wordCounts = words.reduce(incrementWordCount, { });
配列の配列を単一のフラットな配列に減らす:
const concat = (a, b) => a.concat(b);
const numbers = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
].reduce(concat, []);
ものの配列から 1:1 に一致しない単一の値に移行しようとするときはいつでも、reduce を検討することができます。
実際、 map と filter は両方ともリダクションとして実装できます。
const map = (transform, array) =>
array.reduce((list, el) => list.concat(transform(el)), []);
const filter = (predicate, array) => array.reduce(
(list, el) => predicate(el) ? list.concat(el) : list,
[]
);
これにより、 の使用方法に関するさらなるコンテキストが提供されることを願っていますreduce
。
これに加えて、まだ詳しく説明していませんが、配列要素が関数であるため、入力と出力の型が動的であることを明確に意図していることが予想される場合です。
const compose = (...fns) => x =>
fns.reduceRight((x, f) => f(x), x);
const hgfx = h(g(f(x)));
const hgf = compose(h, g, f);
const hgfy = hgf(y);
const hgfz = hgf(z);