Um zu formalisieren, worauf hingewiesen wurde, ist ein Reduzierer ein Katamorphismus, der zwei Argumente verwendet, die zufällig vom gleichen Typ sein können, und einen Typ zurückgibt, der dem ersten Argument entspricht.
function reducer (accumulator: X, currentValue: Y): X { }
Das bedeutet, dass es beim Körper des Reduzierers darum gehen muss, currentValue
den aktuellen Wert von accumulator
in den Wert des neuen umzuwandeln accumulator
.
Dies funktioniert beim Hinzufügen auf einfache Weise, da sowohl der Akkumulator- als auch der Elementwert vom selben Typ sind (aber unterschiedlichen Zwecken dienen).
[1, 2, 3].reduce((x, y) => x + y);
Das funktioniert nur, weil sie alle Zahlen sind.
[{ age: 5 }, { age: 2 }, { age: 8 }]
.reduce((total, thing) => total + thing.age, 0);
Jetzt geben wir dem Aggregator einen Startwert. Der Startwert sollte in den allermeisten Fällen der Typ sein, den Sie vom Aggregator erwarten (der Typ, von dem Sie erwarten, dass er als Endwert herauskommt). Sie sind zwar nicht dazu gezwungen (und sollten es auch nicht sein), aber es ist wichtig, dies zu berücksichtigen.
Sobald Sie das wissen, können Sie sinnvolle Reduzierungen für andere n: 1-Beziehungsprobleme schreiben.
Wiederholte Wörter entfernen:
const skipIfAlreadyFound = (words, word) => words.includes(word)
? words
: words.concat(word);
const deduplicatedWords = aBunchOfWords.reduce(skipIfAlreadyFound, []);
Angabe einer Anzahl aller gefundenen Wörter:
const incrementWordCount = (counts, word) => {
counts[word] = (counts[word] || 0) + 1;
return counts;
};
const wordCounts = words.reduce(incrementWordCount, { });
Reduzieren eines Arrays von Arrays auf ein einzelnes flaches Array:
const concat = (a, b) => a.concat(b);
const numbers = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
].reduce(concat, []);
Jedes Mal, wenn Sie von einer Reihe von Dingen zu einem einzelnen Wert wechseln möchten, der nicht 1: 1 entspricht, sollten Sie eine Reduzierung in Betracht ziehen.
Tatsächlich können sowohl Map als auch Filter als Reduzierungen implementiert werden:
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,
[]
);
Ich hoffe, dies bietet einen weiteren Kontext für die Verwendung reduce
.
Die einzige Ergänzung, auf die ich noch nicht eingegangen bin, ist die Erwartung, dass die Eingabe- und Ausgabetypen speziell dynamisch sein sollen, da die Array-Elemente Funktionen sind:
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);
arr.reduce(function(a,b){return a + b})
im zweiten Beispiel.