Zusammenfassung: Sie können zuerst Ihr Array filtern und dann Ihre Abbildung durchführen, aber dies erfordert zwei Durchläufe des Arrays (Filter gibt ein Array zurück, um zu kartieren). Da dieses Array klein ist, ist der Leistungsaufwand sehr gering. Sie können auch ein einfaches Reduzieren durchführen. Wenn Sie jedoch neu überlegen möchten, wie dies mit einem einzigen Durchlauf über das Array (oder einen beliebigen Datentyp) gemacht werden kann, können Sie eine Idee namens "Transducers" verwenden, die von Rich Hickey populär gemacht wurde.
Antwort:
Wir sollten nicht verlangen, die Punktketten zu erhöhen und auf dem Array [].map(fn1).filter(f2)...
zu arbeiten, da dieser Ansatz Zwischenarrays im Speicher für jede Reduzierungsfunktion
erstellt.
Der beste Ansatz basiert auf der eigentlichen Reduzierungsfunktion, sodass nur ein Daten-Durchlauf durchgeführt wird und keine zusätzlichen Arrays vorhanden sind.
Die Reduzierungsfunktion ist die Funktion, die an reduce
übergeben wird und einen Akkumulator und Eingaben aus der Quelle annimmt und etwas zurückgibt, das wie der Akkumulator aussieht.
// 1. Erstellen Sie eine Verkettungsreduktionsfunktion, die in `reduce` übergeben werden kann
const concat = (acc, input) => acc.concat([input])
// Beachten Sie, dass [1,2,3].reduce(concat, []) [1,2,3] zurückgeben würde
// Ihr Reduzierungsfunktion durch kartieren transformieren
// 2. Erstellen Sie eine generische Kartierungsfunktion, die eine Reduzierungsfunktion einnehmen und eine andere Reduzierungsfunktion zurückgeben kann
const mapping = (changeInput) => (reduzieren) => (acc, input) => reduzieren(acc, changeInput(input))
// 3. Erstellen Sie Ihre Kartierungsfunktion, die auf einen Eingang wirkt
const getSrc = (x) => x.src
const mappingSrc = mapping(getSrc)
// 4. Jetzt können wir unsere `mapSrc`-Funktion verwenden, um unsere ursprüngliche Funktion `concat` zu transformieren und eine andere Reduzierungsfunktion zu erhalten
const inputSources = [{src:'one.html'}, {src:'two.txt'}, {src:'three.json'}]
inputSources.reduce(mappingSrc(concat), [])
// -> ['one.html', 'two.txt', 'three.json']
// Denken Sie daran, dass dies im Grunde genommen nur
// inputSources.reduce((acc, x) => acc.concat([x.src]), [])
// Ihre Reduzierungsfunktion durch Filtern transformieren
// 5. Erstellen Sie eine generische Filterungsfunktion, die eine Reduzierungsfunktion einnehmen und eine andere Reduzierungsfunktion zurückgeben kann
const filtering = (Prädikat) => (reduzieren) => (acc, input) => (Prädikat(input) ? reduzieren(acc, input): acc)
// 6. Erstellen Sie Ihre Filterfunktion, die auf einen Eingang wirken
const filterJsonAndLoad = (img) => {
console.log(img)
if(img.src.split('.').pop() === 'json') {
// game.loadSprite(...);
return false;
} else {
return true;
}
}
const filteringJson = filtering(filterJsonAndLoad)
// 7. Beachten Sie den Typ des Eingangs und des Ausgangs dieser Funktionen
// concat ist eine Reduzierungsfunktion,
// mapSrc transformiert und gibt eine Reduzierungsfunktion zurück
// filterJsonAndLoad transformiert und gibt eine Reduzierungsfunktion zurück
// Diese Funktionen, die Reduzierungsfunktionen transformieren, werden als "Transducers" bezeichnet, von Rich Hickey benannt
// Quelle: http://clojure.com/blog/2012/05/15/anatomy-of-reducer.html
// Wir können dies alles in reduce! geben und ohne Zwischenarrays auskommen
const sources = inputSources.reduce(filteringJson(mappingSrc(concat)), []);
// ['one.html', 'two.txt']
// ==================================
// 8. BONUS: Alle Funktionen zusammenfügen
// Sie können beschließen, eine zusammensetzende Funktion zu erstellen, die eine unendliche Anzahl von Transducers aufnimmt, um auf Ihre Reduzierungsfunktion zu wirken und einen berechneten Akkumulator ohne jemals dieses Zwischenarray zu erstellen, zusammenzusetzen
const composeAll = (...args) => (x) => {
const fns = args
var i = fns.length
while (i--) {
x = fns[i].call(this, x);
}
return x
}
const doABunchOfStuff = composeAll(
filtering((x) => x.src.split('.').pop() !== 'json'),
mapping((x) => x.src),
mapping((x) => x.toUpperCase()),
mapping((x) => x + '!!!')
)
const sources2 = inputSources.reduce(doABunchOfStuff(concat), [])
// ['ONE.HTML!!!', 'TWO.TXT!!!']
Ressourcen: Reicher Hickey Transducers Beitrag