Eine Anleitung zur Reduzierungsmethode in Javascript

Die Reduktionsmethode von JavaScript ist einer der Eckpfeiler der funktionalen Programmierung.Lassen Sie uns untersuchen, wie es funktioniert, wann Sie es verwenden sollten und welche coolen Dinge es tun kann.

Eine grundlegende Reduzierung

Verwenden Sie es, wenn : Sie eine Reihe von Beträgen haben und diese alle addieren möchten.

const euros = [29.76, 41.85, 46.5]; const sum = euros.reduce((total, amount) => total + amount); sum // 118.11

Wie man es benutzt:

  • In diesem Beispiel akzeptiert Reduzieren zwei Parameter, den Gesamtbetrag und den aktuellen Betrag.
  • Die Reduktionsmethode durchläuft jede Zahl im Array ähnlich wie in einer for-Schleife.
  • Wenn die Schleife startet, ist der Gesamtwert die Zahl ganz links (29,76) und der aktuelle Betrag ist der daneben (41,85).
  • In diesem Beispiel möchten wir den aktuellen Betrag zur Gesamtsumme hinzufügen.
  • Die Berechnung wird für jeden Betrag im Array wiederholt, aber jedes Mal, wenn der aktuelle Wert zur nächsten Zahl im Array wechselt, wird nach rechts verschoben.
  • Wenn das Array keine Zahlen mehr enthält, gibt die Methode den Gesamtwert zurück.

Die ES5-Version der Reduce-Methode in JavaScript

Wenn Sie noch nie zuvor die ES6-Syntax verwendet haben, lassen Sie sich vom obigen Beispiel nicht einschüchtern. Es ist genau das gleiche wie beim Schreiben:

var euros = [29.76, 41.85, 46.5]; var sum = euros.reduce( function(total, amount){ return total + amount }); sum // 118.11

Wir verwenden constanstelle von varund ersetzen das Wort functiondurch einen "fetten Pfeil" ( =>) nach den Parametern, und wir lassen das Wort "return" weg.

Ich werde für den Rest der Beispiele die ES6-Syntax verwenden, da sie prägnanter ist und weniger Raum für Fehler lässt.

Ermitteln eines Durchschnitts mit der Reduce-Methode in JavaScript

Anstatt die Summe zu protokollieren, können Sie die Summe durch die Länge des Arrays dividieren, bevor Sie einen endgültigen Wert zurückgeben.

Der Weg, dies zu tun, besteht darin, die anderen Argumente in der Reduktionsmethode zu nutzen. Das erste dieser Argumente ist der Index . Ähnlich wie bei einer for-Schleife bezieht sich der Index auf die Häufigkeit, mit der der Reduzierer das Array durchlaufen hat. Das letzte Argument ist das Array selbst.

const euros = [29.76, 41.85, 46.5]; const average = euros.reduce((total, amount, index, array) => { total += amount; if( index === array.length-1) { return total/array.length; }else { return total; } }); average // 39.37

Karte und Filter als Verkleinerung

Wenn Sie die Reduzierungsfunktion verwenden können, um einen Durchschnitt auszuspucken, können Sie sie nach Belieben verwenden.

Zum Beispiel könnten Sie die Summe verdoppeln, oder jede halbe Zahl vor ihnen zusammen addieren, oder ein im Innern des Minderer nur hinzufügen Zahlen if - Anweisung verwenden, die größer als 10 Mein Punkt ist , dass die Reduzierung der Methode In JavaScript gibt Ihnen einen Mini CodePen, in den Sie jede gewünschte Logik schreiben können. Es wiederholt die Logik für jeden Betrag im Array und gibt dann einen einzelnen Wert zurück.

Die Sache ist, dass Sie nicht immer einen einzelnen Wert zurückgeben müssen. Sie können ein Array in ein neues Array reduzieren.

Reduzieren Sie beispielsweise ein Array von Beträgen in ein anderes Array, in dem jeder Betrag verdoppelt wird. Dazu müssen wir den Anfangswert für unseren Akkumulator auf ein leeres Array setzen.

Der Anfangswert ist der Wert des Gesamtparameters zu Beginn der Reduzierung. Sie legen den Anfangswert fest, indem Sie ein Komma gefolgt von Ihrem Anfangswert in Klammern, jedoch nach den geschweiften Klammern ( im folgenden Beispiel fett gedruckt ) hinzufügen .

const average = euros.reduce((total, amount, index, array) => { total += amount return total/array.length }, 0);

In den vorherigen Beispielen war der Anfangswert Null, daher habe ich ihn weggelassen. Durch den Anfangswert Weglassen der insgesamt wird auf die erste Menge in dem Array Standard.

Indem wir den Anfangswert auf ein leeres Array setzen, können wir jeden Betrag in die Summe verschieben . Wenn wir ein Array von Werten in ein anderes Array reduzieren möchten, in dem jeder Wert verdoppelt wird, müssen wir den Betrag * 2 verschieben. Dann geben wir die Summe zurück, wenn keine weiteren Beträge mehr zu pushen sind.

const euros = [29.76, 41.85, 46.5]; const doubled = euros.reduce((total, amount) => { total.push(amount * 2); return total; }, []); doubled // [59.52, 83.7, 93]

Wir haben ein neues Array erstellt, in dem jeder Betrag verdoppelt wird. Wir könnten auch Zahlen herausfiltern, die wir nicht verdoppeln möchten, indem wir eine if-Anweisung in unseren Reduzierer einfügen.

const euro = [29.76, 41.85, 46.5]; const above30 = euro.reduce((total, amount) => { if (amount > 30) { total.push(amount); } return total; }, []); above30 // [ 41.85, 46.5 ]

Diese Operationen sind die Karten- und Filtermethoden , die als Reduzierungsmethode umgeschrieben wurden.

Für diese Beispiele wäre es sinnvoller, Map oder Filter zu verwenden, da sie einfacher zu verwenden sind. Der Vorteil der Verwendung von Reduzieren kommt zum Tragen, wenn Sie gemeinsam abbilden und filtern möchten und viele Daten zu verarbeiten sind.

Wenn Sie Map verketten und filtern, erledigen Sie die Arbeit zweimal. Sie filtern jeden einzelnen Wert und ordnen dann die verbleibenden Werte zu. Mit Reduzieren können Sie filtern und dann in einem einzigen Durchgang zuordnen.

Verwenden Sie Map und Filter. Wenn Sie jedoch viele Methoden miteinander verketten, wissen Sie jetzt, dass es schneller ist, die Daten zu reduzieren.

Erstellen einer Tally mit der Reduce-Methode in JavaScript

Verwenden Sie es, wenn : Sie eine Sammlung von Elementen haben und wissen möchten, wie viele Elemente sich in der Sammlung befinden.

const fruitBasket = ['banana', 'cherry', 'orange', 'apple', 'cherry', 'orange', 'apple', 'banana', 'cherry', 'orange', 'fig' ]; const count = fruitBasket.reduce( (tally, fruit) =>  , {}) count // { banana: 2, cherry: 3, orange: 3, apple: 2, fig: 1 }

Um Elemente in einem Array zu zählen, muss unser Anfangswert ein leeres Objekt sein, kein leeres Array wie im letzten Beispiel.

Da wir ein Objekt zurückgeben werden, können wir jetzt Schlüssel-Wert-Paare in der Summe speichern.

fruitBasket.reduce( (tally, fruit) => { tally[fruit] = 1; return tally; }, {})

Bei unserem ersten Durchgang möchten wir, dass der Name des ersten Schlüssels unser aktueller Wert ist, und wir möchten ihm den Wert 1 geben.

Dies gibt uns ein Objekt mit allen Früchten als Schlüsseln mit einem Wert von jeweils 1. Wir möchten, dass sich die Menge jeder Frucht erhöht, wenn sie sich wiederholen.

Zu diesem Zweck prüfen wir in unserer zweiten Schleife, ob unsere Summe einen Schlüssel mit der aktuellen Frucht des Reduzierers enthält. Wenn nicht, erstellen wir es. Wenn dies der Fall ist, erhöhen wir den Betrag um eins.

fruitBasket.reduce((tally, fruit) => { if (!tally[fruit]) { tally[fruit] = 1; } else { tally[fruit] = tally[fruit] + 1; } return tally; }, {});

I rewrote the exact same logic in a more concise way up top.

Flattening an array of arrays with the Reduce Method In JavaScript​​

We can use reduce to flatten nested amounts into a single array.

We set the initial value to an empty array and then concatenate the current value to the total.

const data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; const flat = data.reduce((total, amount) => { return total.concat(amount); }, []); flat // [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

More often than not, information is nested in more complicated ways. For instance, lets say we just want all the colors in the data variable below.

const data = [ {a: 'happy', b: 'robin', c: ['blue','green']}, {a: 'tired', b: 'panther', c: ['green','black','orange','blue']}, {a: 'sad', b: 'goldfish', c: ['green','red']} ];

We’re going to step through each object and pull out the colours. We do this by pointing amount.c for each object in the array. We then use a forEach loop to push every value in the nested array into out total.

const colors = data.reduce((total, amount) => { amount.c.forEach( color => { total.push(color); }) return total; }, []) colors //['blue','green','green','black','orange','blue','green','red']

If we only need unique number then we can check to see of the number already exists in total before we push it.

const uniqueColors = data.reduce((total, amount) => { amount.c.forEach( color => { if (total.indexOf(color) === -1){ total.push(color); } }); return total; }, []); uniqueColors // [ 'blue', 'red', 'green', 'black', 'orange']

Piping with Reduce

An interesting aspect of the reduce method in JavaScript is that you can reduce over functions as well as numbers and strings.

Let’s say we have a collection of simple mathematical functions. these functions allow us to increment, decrement, double and halve an amount.

function increment(input) { return input + 1;} function decrement(input) { return input — 1; } function double(input) { return input * 2; } function halve(input) { return input / 2; }

For whatever reason, we need to increment, then double, then decrement an amount.

You could write a function that takes an input, and returns (input + 1) * 2 -1. The problem is that we know we are going to need to increment the amount three times, then double it, then decrement it, and then halve it at some point in the future. We don’t want to have to rewrite our function every time so we going to use reduce to create a pipeline.

A pipeline is a term used for a list of functions that transform some initial value into a final value. Our pipeline will consist of our three functions in the order that we want to use them.

let pipeline = [increment, double, decrement];

Instead of reducing an array of values we reduce over our pipeline of functions. This works because we set the initial value as the amount we want to transform.

const result = pipeline.reduce(function(total, func) { return func(total); }, 1); result // 3

Because the pipeline is an array, it can be easily modified. If we want to decrement something three times, then double it, decrement it , and halve it then we just alter the pipeline.

var pipeline = [ increment, increment, increment, double, decrement, halve ];

The reduce function stays exactly the same.

Silly Mistakes to avoid

If you don’t pass in an initial value, reduce will assume the first item in your array is your initial value. This worked fine in the first few examples because we were adding up a list of numbers.

If you’re trying to tally up fruit, and you leave out the initial value then things get weird. Not entering an initial value is an easy mistake to make and one of the first things you should check when debugging.

Another common mistake is to forget to return the total. You must return something for the reduce function to work. Always double check and make sure that you’re actually returning the value you want.

Tools, Tips & References

  • Everything in this post came from a fantastic video series on egghead called Introducing Reduce. I give Mykola Bilokonsky full credit and I am grateful to him for everything I now know about using the Reduce Method In JavaScript​. I have tried to rewrite much of what he explains in my own words as an exercise to better understand each concept. Also, it’s easier for me to reference an article, as opposed to a video, when I need to remember how to do something.
  • The MDN Reduce documentation labels what I called a total the accumulator. It is important to know this because most people will refer to it as an accumulator if you read about it online. Some people call it prev as in previous value. It all refers to the same thing. I found it easier to think of a total when I was learning reduce.
  • If you would like to practice using reduce I recommend signing up to freeCodeCamp and completing as many of the intermediate algorithms as you can using reduce.
  • If the ‘const’ variables in the example snippets are new to you I wrote another article about ES6 variables and why you might want to use them.
  • I also wrote an article called The Trouble With Loops that explain how to use map() and filter() if the are new to you.

Thanks for reading! If you’d like to be notified when I write a new article please enter your email here.

And if you liked the article, please share it on social media so others can find it.