Detaillierte Erklärung von JavaScript Reduce

Detaillierte Erklärung von JavaScript Reduce

Das Erlernen dieser Fähigkeit Reduce wird Ihnen eine neue Welt der Programmierung eröffnen

Wenn Sie diese Reduce Fähigkeit erlernen, öffnet sich Ihnen eine ganz neue Welt 🎉

reduce ist die flexibelste JS-Array-Methode, da sie andere Array-Methoden wie map / filter / some / every usw. ersetzen kann. Es ist auch die am schwierigsten zu verstehende Methode. Viele Lodash-Methoden können damit ebenfalls implementiert werden. Das Erlernen von Reduce bietet Entwicklern eine andere funktionale und deklarative Perspektive zur Problemlösung als die bisherige prozedurale oder imperative Perspektive.

Eine der Schwierigkeiten besteht darin, den Typ von acc ( accumulation ) zu bestimmen und den Anfangswert zu wählen. Tatsächlich gibt es einen kleinen Trick, der uns helfen kann, einen geeigneten Anfangswert zu finden. Der Typ des gewünschten Rückgabewerts muss mit dem Typ von acc übereinstimmen. Wenn beispielsweise das Endergebnis der Summe eine Zahl ist, sollte acc ein Zahlentyp sein, daher muss seine Initialisierung 0 sein.

Beginnen wir mit der Festigung unseres Verständnisses und unserer Verwendung von reduce .

Karte

Gemäß den Tipps ist der endgültige Rückgabewert von map ein Array, daher sollte acc auch ein Array sein und als Anfangswert kann ein leeres Array verwendet werden.

/**
 * Verwenden Sie „reduce“, um die integrierte Methode „Array.prototype.map“ zu implementieren.
 * @param {any[]} arr 
 * @param {(val: any, index: number, thisArray: any[]) => jede} Zuordnung 
 * @returns {any[]}
 */
Funktion map(arr, Mapping) {
 return arr.reduce((acc, item, index) => [...acc, Zuordnung(item, index, arr)], []);
}

prüfen

Karte([null, false, 1, 0, '', () => {}, NaN], val => !!val);

// [falsch, falsch, wahr, falsch, falsch, wahr, falsch]

Filter

Den Tipps zufolge ist der endgültige Rückgabewert des filter ebenfalls ein Array, sodass acc ebenfalls ein Array sein sollte und ein leeres Array verwendet werden kann.

/**
 * Verwenden Sie „reduce“, um die integrierte Methode „Array.prototype.filter“ zu implementieren.
 * @param {any[]} arr 
 * @param {(val: any, index: number, thisArray: any[]) => boolean} Prädikat 
 * @returns {any[]}
 */
Funktion Filter(arr, Prädikat) {
 return arr.reduce((acc, item, index) => Prädikat(item, index, arr) ? [...acc, item] : acc, []);
}

prüfen

Filter([null, false, 1, 0, '', () => {}, NaN], Wert => !!Wert);

// [1, () => {}]

manche

some gibt false zurück, wenn das Zielarray leer ist, sodass der Anfangswert false ist.

Funktion einige (arr, Prädikat) {
 return arr.reduce((acc, val, idx) => acc || Prädikat(val, idx, arr), false)
}

prüfen:

einige([null, falsch, 1, 0, '', () => {}, NaN], val => !!val);
// WAHR

einige([null, falsch, 0, '', NaN], val => !!val);
// FALSCH

Zur Erinnerung: Die beiden haben keinen Einfluss auf das Ergebnis, weisen aber Leistungsunterschiede auf. Das Platzieren von acc an den Anfang ist ein Kurzschlussalgorithmus, der unnötige Berechnungen vermeiden kann und somit eine höhere Leistung aufweist.

acc || Prädikat(val, idx, arr)

Und

Prädikat(Wert, Idx, Arr) || Acc

jeder

Wenn every Zielarray leer ist, wird true zurückgegeben, sodass der Anfangswert true ist.

Funktion every(arr, Prädikat) {
 return arr.reduce((acc, val, idx) => acc und Prädikat(val, idx, arr), true)
}

Index suchen

Wenn das Zielarray findIndex leer ist, wird -1 zurückgegeben, sodass der Anfangswert -1 ist.

Funktion findIndex(arr, Prädikat) {
 const NOT_FOUND_INDEX = -1;

 return arr.reduce((acc, val, idx) => {
 if (acc === NICHT_GEFUNDENER_INDEX) {
 Prädikat (Wert, IDX, Arr) zurückgeben? IDX: NICHT GEFUNDENER INDEX;
 }
 
 Rückgabe gem.
 }, INDEX_NICHT_GEFUNDEN)
}

prüfen

findIndex([5, 12, 8, 130, 44], (Element) => Element > 8) // 3

Rohr

1. Implementieren Sie die folgenden Funktionen

/**
 * Gibt eine Funktion zurück, um den Eingabewert von den bereitgestellten Funktionen der Reihe nach von links nach rechts verarbeiten zu lassen.
 * @param {(funcs: any[]) => beliebige} Funktionen 
 * @returns {(arg: any) => any}
 */
Funktion Pipe(...Funktionen) {}

Machen

pipe(Wert => Wert * 2, Math.sqrt, Wert => Wert + 10)(2) // 12

Mit dieser Funktion können komplexere Verarbeitungsprozesse implementiert werden.

// Wähle die Elemente aus, deren Wert positiv ist, multipliziere ihren Wert mit 0,1, addiere dann den Wert aller Elemente und erhalte schließlich 3
const Prozess = Pipe(
 arr => arr.filter(({ val }) => val > 0), 
 arr => arr.map(Element => ({ ...Element, Wert: Element.Wert * 0,1 })), 
 arr => arr.reduce((acc, { val }) => acc + val, 0)
);

Prozess([{ Wert: -10 }, { Wert: 20 }, { Wert: -0,1 }, { Wert: 10 }]) // 3

2. Implementieren Sie die folgende Funktion, die die Funktion der obigen Pipe realisieren und eine Funktion zurückgeben kann, die eine unbestimmte Anzahl von Parametern akzeptiert.

/**
 * Gibt eine Funktion zurück, die die Eingabewerte von den bereitgestellten Funktionen der Reihe nach von links nach rechts verarbeiten lässt.
 * @param {(funcs: any[]) => beliebige} Funktionen 
 * @returns {(args: any[]) => any}
 */
Funktion Pipe(...Funktionen) {}

Führen Sie den folgenden einzelnen Testdurchlauf durch

pipe(Summe, Math.sqrt, Wert => Wert + 10)(0,1, 0,2, 0,7, 3) // 12

Unter ihnen wurde sum realisiert

/**
 * Addieren Sie die Zahlen.
 * @param args Nummer[]
 * @returns {number} die Gesamtsumme.
 */
Funktion Summe(...args) {
 gibt args.reduce((a, b) => a + b); zurück
}

Referenzantwort

1. Rückgabe einer Funktion, die einen Parameter akzeptiert

Lassen Sie den Funktionsschritt zum Herausfiltern von Nichtfunktionen aus.

/**
 * Gibt eine Funktion zurück, um den Eingabewert von den bereitgestellten Funktionen der Reihe nach von links nach rechts verarbeiten zu lassen.
 * @param {(arg: any) => any} Funktionen
 * @returns {(arg: any) => any}
 */
Funktion Pipe(...Funktionen) {
 return (arg) => {
 Rückgabefunktion.Reduce(
 (acc, Funktion) => Funktion(acc),
 arg
 )
 }
}

2. Rückgabefunktionen akzeptieren unbestimmte Parameter

Der Funktionsschritt zum Herausfiltern von Nicht-Funktionen wird ebenfalls ausgelassen.

/**
 * Gibt eine Funktion zurück, um den Eingabewert von den bereitgestellten Funktionen der Reihe nach von links nach rechts verarbeiten zu lassen.
 * @param {Array<(...args: any) => any>} Funktionen
 * @returns {(...args: any[]) => any}
 */
Funktion Pipe(...Funktionen) {
	// const realFuncs = funcs.filter(isFunction);

 return (...args) => {
 Rückgabefunktion.Reduce(
 (acc, func, idx) => idx === 0 ? func(...acc) : func(acc),
 Argumente
 )
 }
}

Bessere Schreibleistung, Vermeidung unnötiger Vergleiche und CPU-Verschwendung

Funktion Pipe(...Funktionen) {
 return (...args) => {
 // Der erste wurde verarbeitet, nur die restlichen müssen verarbeitet werden return funcs.slice(1).reduce(
 (acc, Funktion) => Funktion(acc),
 
 // Behandeln Sie zuerst den Sonderfall als „acc“
 Funktionen[0](...Argumente)
 )
 }
}

Achten Sie auf die Fallstricke der zweiten Schreibweise funcs[0](...args) . Wenn das Array leer ist, explodiert es aufgrund des Nullzeigers.

Implementierung von lodash.get

Durch die Implementierung von get wird im folgenden Beispiel 'hello world' zurückgegeben.

const obj = { a: { b: { c: 'Hallo Welt' } } };

erhalte(Objekt, 'abc');

Funktionssignatur:

/**
 * Den Wert über den Schlüsselpfad abfragen
 * @param beliebiges Objekt
 * @param keyPath Zeichenfolge durch Punkte getrennter Schlüsselpfad* @returns {any} Zielwert*/
Funktion get(Objekt, Schlüsselpfad) {}

Referenzantwort

/**
 * Wählen Sie den Wert über den Schlüsselpfad aus.
 * @param beliebiges Objekt
 * @param keyPath Zeichenfolge durch Punkte getrennter Schlüsselpfad* @returns {any} Zielwert*/
Funktion get(Objekt, Schlüsselpfad) {
 wenn (!obj) {
 Rückgabe undefiniert;
 }

 returniere keyPath.split('.').reduce((acc, key) => acc[key], obj);
}

Implementierung von lodash.flattenDeep

Obwohl Concat- und Spread-Operatoren nur eine Ebene abflachen können, kann durch Rekursion eine tiefe Abflachung erreicht werden.

Methode 1: Spread-Operator

Funktion flatDeep(arr) {
 Rückgabewert arr.reduce((acc, item) => 
 Array.isArray(Element) ? [...acc, ...flatDeep(Element)] : [...acc, Element],
 []
 )
}

Methode 2: concat

Funktion flatDeep(arr) {
 Rückgabewert arr.reduce((acc, item) => 
 acc.concat(Array.isArray(Element) ? flatDeep(Element) : Element),
 []
 )
}

Interessanter Leistungsvergleich: Der Expansionsoperator benötigt 1098 ms, um 70.000 Mal ausgeführt zu werden, während concat in der gleichen Zeit nur 20.000 Mal ausgeführt werden kann.

Funktion flatDeep(arr) {
 Rückgabewert arr.reduce((acc, item) => 
 Array.isArray(Element) ? [...acc, ...flatDeep(Element)] : [...acc, Element],
 []
 )
}

var arr = Wiederholung([1, [2], [[3]], [[[4]]]], 20);

Konsole.log(arr);
Konsole.log(flatDeep(arr));

Konsole.Zeit('concat')
für (i = 0; i < 7 * 10000; ++i) {
 flatDeep(arr)
}
Konsole.timeEnd('concat')

Funktion „Wiederholung (arr, mal)“ { „let Ergebnis = []; für (i = 0; i < mal; ++i) { „ergebnis.push(...arr)“} „return Ergebnis“;}

Nullwerte in einem Objekt herausfiltern

erreichen

sauber({ foo: null, bar: undefiniert, baz: 'hallo' })

// { baz: 'hallo' }

Antwort

/**
 * Filtern Sie die „Nil“-Werte (null oder undefiniert) heraus.
 * @param {Objekt} Objekt
 * @returns {any}
 *
 * @example clean({ foo: null, bar: undefiniert, baz: 'hallo' })
 *
 * // => { baz: 'hallo' }
 */
Exportfunktion clean(obj) {
 wenn (!obj) {
 gibt Objekt zurück;
 }

 returniere Objekt.Schlüssel(Objekt).Reduce((acc, Schlüssel) => {
 wenn (!isNil(obj[Schlüssel])) {
 acc[Schlüssel] = obj[Schlüssel];
 }

 Rückgabe gem.
 }, {});
}

aufzählen

Simulieren Sie konstante Objekte als TS-Aufzählungen

Implementieren Sie enumify damit

const Richtung = {
 Oben: 0,
 NACH UNTEN: 1,
 LINKS: 2,
 RECHTS: 3,
};

const actual = aufzählen(Richtung);

Konstante erwartet = {
 Oben: 0,
 NACH UNTEN: 1,
 LINKS: 2,
 RECHTS: 3,

 0: 'AUF',
 1: 'UNTEN',
 2: 'LINKS',
 3: 'RECHTS',
};

deepStrictEqual(tatsächlich, erwartet);

Antwort:

/**
 * Enumeration aus Objekt generieren.
 * @siehe https://www.typescriptlang.org/play?#code/KYOwrgtgBAglDeAoKUBOwAmUC8UCMANMmpgEw5SlEC+UiiAxgPYgDOTANsAHQdMDmAChjd0GAJQBuRi3ZdeA4QG08AXSmIgA
 * @param {Objekt} Objekt
 * @returns {Objekt}
 */
Exportfunktion enumify(obj) {
 wenn (!isPlainObject(obj)) {
 throw new TypeError('das Enumify-Ziel muss ein einfaches Objekt sein');
 }

 returniere Objekt.Schlüssel(Objekt).Reduce((acc, Schlüssel) => {
 acc[Schlüssel] = obj[Schlüssel];
 acc[Objekt[Schlüssel]] = Schlüssel;

 Rückgabe gem.
 }, {});
}

Serienvollstrecker für Versprechen

Durch die Verwendung von „Reduce“ können wir eine unbegrenzte Anzahl von Promises seriell ausführen, was in tatsächlichen Projekten eine große Rolle spielen kann. Ich werde hier nicht ins Detail gehen. Bitte lesen Sie meinen nächsten Artikel „JS Request Scheduler“.

expandieren

Bitte verwenden Sie Jest als Testframework und schreiben Sie Unit-Tests für alle Methoden in diesem Artikel. Weitere Übungen finden Sie unter github.com/you-dont-ne…

Oben finden Sie den detaillierten Inhalt der ausführlichen Erläuterung zur Verwendung von JavaScript Reduce. Weitere Informationen zur Verwendung von JavaScript Reduce finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • 5 grundlegende Anwendungsbeispiele von reduce() in JavaScript
  • JavaScript-Array-Reduzierungsmethode ()
  • 8 JS reduziert Verwendungsbeispiele und reduzierte Betriebsmethoden
  • Zusammenfassung zur Verwendung der Reduce()-Methode in JS
  • js verwendet die Reduce-Methode, um Ihren Code eleganter zu gestalten
  • Detaillierte Erläuterung der grundlegenden Verwendung von JavaScript Reduce

<<:  CentOS7 64-Bit-Installation MySQL Grafik-Tutorial

>>:  Packetdrills prägnantes Benutzerhandbuch

Artikel empfehlen

Detaillierte Erklärung der MySQL-Berechtigungen und -Indizes

MySQL-Berechtigungen und Indizes Der höchste Benu...

Detaillierte Erklärung der MySQL-Halbsynchronisierung

Inhaltsverzeichnis Vorwort MySQL Master-Slave-Rep...

Regeln für die Verwendung gemeinsamer MySQL-Indizes

Ein gemeinsamer Index wird auch als zusammengeset...

Beispiel zum Ändern der inländischen Quelle in Ubuntu 18.04

Die eigene Quelle von Ubuntu stammt aus China, da...

Techniken zur Wiederverwendung von HTML

HTML-Wiederverwendung ist ein Begriff, der selten ...

Verwendung des Linux Dig-Befehls

Dig-Einführung: Dig ist ein Tool, das DNS einschl...