Hier ist eine aktualisierte Version des Codes, bereitgestellt von @theprtk. Es wurde ein wenig aufgeräumt, um die verallgemeinerte Version anzuzeigen, während ein Beispiel vorhanden ist.
Hinweis: Ich würde das gerne als Kommentar zu seinem Beitrag hinzufügen, aber ich habe noch nicht genug Reputation
/**
* @siehe http://clojure.com/blog/2012/05/15/anatomy-of-reducer.html
* @Beschreibung Funktionen, die reduzierende Funktionen transformieren
*/
const transduce = {
/** ein generisches map(), das eine reducing() entgegennehmen kann und eine andere reducing() zurückgibt */
map: changeInput => reducing => (acc, input) =>
reducing(acc, changeInput(input)),
/** ein generisches filter(), das eine reducing() entgegennehmen kann und zurückgibt */
filter: predicate => reducing => (acc, input) =>
predicate(input) ? reducing(acc, input) : acc,
/**
* ein composing() der eine unendlich lange Anzahl von Transducern entgegennehmen kann
* reduzierende Funktionen, um einen berechneten Akkumulator zu komponieren, ohne jemals
* das Zwischenarray zu erstellen
*/
compose: (...args) => x => {
const fns = args;
var i = fns.length;
while (i--) x = fns[i].call(this, x);
return x;
},
};
const example = {
data: [{ src: 'file.html' }, { src: 'file.txt' }, { src: 'file.json' }],
/** Hinweis: `[1,2,3].reduce(concat, [])` -> `[1,2,3]` */
concat: (acc, input) => acc.concat([input]),
getSrc: x => x.src,
filterJson: x => x.src.split('.').pop() !== 'json',
};
/** Schritt 1: Erstellen einer reduzierenden Funktion, die an `reduce` übergeben werden kann */
const reduceFn = example.concat;
/** Schritt 2: Transformieren Ihrer reduzierenden Funktion durch Mapping */
const mapFn = transduce.map(example.getSrc);
/** Schritt 3: Erstellen Sie Ihre filter() Funktion, die auf einer Eingabe operiert */
const filterFn = transduce.filter(example.filterJson);
/** Schritt 4: Aggregieren Sie Ihre Transformationen */
const composeFn = transduce.compose(
filterFn,
mapFn,
transduce.map(x => x.toUpperCase() + '!'), // neue Zuordnung()
);
/**
* Erwarteter Beispieloutput
* Hinweis: jedes ist in `example.data.reduce(x, [])` eingewickelt
* 1: ['file.html', 'file.txt', 'file.json']
* 2: ['file.html', 'file.txt']
* 3: ['FILE.HTML!', 'FILE.TXT!']
*/
const exampleFns = {
transducers: [
mapFn(reduceFn),
filterFn(mapFn(reduceFn)),
composeFn(reduceFn),
],
raw: [
(acc, x) => acc.concat([x.src]),
(acc, x) => acc.concat(x.src.split('.').pop() !== 'json' ? [x.src] : []),
(acc, x) => acc.concat(x.src.split('.').pop() !== 'json' ? [x.src.toUpperCase() + '!'] : []),
],
};
const execExample = (currentValue, index) =>
console.log('Beispiel ' + index, example.data.reduce(currentValue, []));
exampleFns.raw.forEach(execExample);
exampleFns.transducers.forEach(execExample);