Для формалізації того, на що вказувалося, редуктор - це катаморфізм, який бере два аргументи, які можуть бути однотипними за збігом обставин, і повертає тип, який відповідає першому аргументу.
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, зменшення - це те, що ви можете врахувати.
Насправді, карта та фільтр можуть бути реалізовані як скорочення:
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);
arr.reduce(function(a,b){return a + b})
на увазі у другому прикладі.