Eine illustrierte (und musikalische) Anleitung zu den Methoden Map, Reduce und Filter für Arrays

Avatar of Una Kravets
Una Kravets am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Map, reduce und filter sind drei sehr nützliche Array-Methoden in JavaScript, die Entwicklern viel Macht auf kleinem Raum geben. Springen wir direkt hinein, wie Sie diese super praktischen Methoden nutzen können (und wie Sie sich erinnern, wie man sie benutzt!).

Array.map()

Array.map() aktualisiert jeden einzelnen Wert in einem gegebenen Array basierend auf einer bereitgestellten Transformation und gibt ein neues Array gleicher Größe zurück. Es akzeptiert eine Callback-Funktion als Argument, die es zur Anwendung der Transformation verwendet.

let newArray = oldArray.map((value, index, array) => {
  ...
});

Ein Merkspruch hierfür ist MAP: Morph Array Piece-by-Piece (Array Stück für Stück formen).

Anstatt einer for-each-Schleife, um diese Transformation auf jeden Wert anzuwenden, können Sie eine Map verwenden. Dies funktioniert, wenn Sie jeden Wert erhalten, ihn aber aktualisieren möchten. Wir eliminieren potenziell keine Werte (wie bei einem Filter) und berechnen keine neue Ausgabe (wie bei Reduce). Eine Map ermöglicht es Ihnen, ein Array Stück für Stück zu formen. Schauen wir uns ein Beispiel an.

[1, 4, 6, 14, 32, 78].map(val => val * 10)
// the result is: [10, 40, 60, 140, 320, 780]

Im obigen Beispiel nehmen wir ein Anfangsarray ([1, 4, 6, 14, 32, 78]) und bilden jeden Wert darin so ab, dass er das Zehnfache des Werts ist (val * 10). Das Ergebnis ist ein neues Array, in dem jeder Wert des ursprünglichen Arrays durch die Gleichung transformiert wurde: [10, 40, 60, 140, 320, 780].

An illustration of the code examples covered in this section.

Array.filter()

Array.filter() ist eine sehr praktische Abkürzung, wenn wir ein Array von Werten haben und diese Werte in ein anderes Array filtern möchten, wobei jeder Wert im neuen Array ein Wert ist, der einen bestimmten Test besteht.

Dies funktioniert wie ein Suchfilter. Wir filtern Werte heraus, die die von uns bereitgestellten Parameter bestehen.

Wenn wir zum Beispiel ein Array von numerischen Werten haben und nur die Werte herausfiltern wollen, die größer als 10 sind, könnten wir schreiben

[1, 4, 6, 14, 32, 78].filter(val => val > 10)
// the result is: [14, 32, 78]

Wenn wir eine Map-Methode auf dieses Array anwenden würden, wie im obigen Beispiel, würden wir ein Array derselben Länge wie das Original zurückgeben, wobei val > 10 die „Transformation“ oder in diesem Fall ein Test wäre. Wir transformieren jeden der ursprünglichen Werte in seine Antwort, wenn er größer als 10 ist. Das würde so aussehen

[1, 4, 6, 14, 32, 78].map(val => val > 10)
// the result is: [false, false, false, true, true, true]

Ein Filter gibt jedoch *nur* die wahren Werte zurück. Das Ergebnis ist also kleiner als das ursprüngliche Array oder gleich groß, wenn alle Werte einen bestimmten Test bestehen.

Denken Sie an **filter** wie an einen Sieb-Filter. Ein Teil der Mischung wird durchgelassen, ein Teil bleibt zurück und wird verworfen.

An illustration of a funnel with numbers going in the top and a few coming out of the bottom next to a handwritten version of the code covered in this section.

Nehmen wir an, wir haben eine (sehr kleine) Klasse von vier Hunden in einer Hundeschule. Alle Hunde hatten während der Hundeschule Herausforderungen und legten eine benotete Abschlussprüfung ab. Wir stellen die Hunde als Array von Objekten dar, d.h.

const students = [
  {
    name: "Boops",
    finalGrade: 80
  },
  {
    name: "Kitten",
    finalGrade: 45
  },
  {
    name: "Taco",
    finalGrade: 100
  },
  {
    name: "Lucy",
    finalGrade: 60
  }
]

Wenn die Hunde eine Punktzahl über 70 in ihrem Abschlusstest erreichen, erhalten sie ein schickes Zertifikat; wenn nicht, müssen sie den Kurs wiederholen. Um zu wissen, wie viele Zertifikate gedruckt werden müssen, müssen wir eine Methode schreiben, die die Hunde mit bestandenen Noten zurückgibt. Anstatt eine Schleife zu schreiben, um jedes Objekt im Array zu testen, können wir unseren Code mit filter kürzen!

const passingDogs = students.filter((student) => {
  return student.finalGrade >= 70
})

/*
passingDogs = [
  {
    name: "Boops",
    finalGrade: 80
  },
  {
    name: "Taco",
    finalGrade: 100
  }
]
*/

Wie Sie sehen können, sind Boops und Taco gute Hunde (eigentlich sind alle Hunde gute Hunde), also bekommen Boops und Taco Leistungszertifikate für das Bestehen des Kurses! Wir können dies mit unseren schönen impliziten Rückgaben in einer einzigen Codezeile schreiben und dann die Klammern von unserer Pfeilfunktion entfernen, da wir ein einzelnes Argument haben.

const passingDogs = students.filter(student => student.finalGrade >= 70)

/*
passingDogs = [
  {
    name: "Boops",
    finalGrade: 80
  },
  {
    name: "Taco",
    finalGrade: 100
  }
]
*/

Array.reduce()

Die Methode reduce() nimmt die Eingabewerte eines Arrays und gibt einen einzelnen Wert zurück. Diese ist wirklich interessant. Reduce akzeptiert eine Callback-Funktion, die aus einem Akkumulator (ein Wert, der jedes Stück des Arrays sammelt, wie ein Schneeball wächst), dem Wert selbst und dem Index besteht. Sie nimmt auch einen Startwert als zweites Argument an.

let finalVal = oldArray.reduce((accumulator, currentValue, currentIndex, array) => {
  ...
}), initalValue;
An illustration of a saucepan cooking ingredients next to handwritten code from the examples covered in this section.

Lassen Sie uns eine Kochfunktion und eine Liste von Zutaten aufstellen.

// our list of ingredients in an array
const ingredients = ['wine', 'tomato', 'onion', 'mushroom']

// a cooking function
const cook = (ingredient) => {
    return `cooked ${ingredient}`
}

Wenn wir die Zutaten zu einer Sauce reduzieren wollen (Wortspiel absolut beabsichtigt), reduzieren wir sie mit reduce()!

const wineReduction = ingredients.reduce((sauce, item) => {
  return sauce += cook(item) + ', '
  }, '')
  
// wineReduction = "cooked wine, cooked tomato, cooked onion, cooked mushroom, "

Dieser Anfangswert (in unserem Fall '') ist wichtig, denn wenn wir ihn nicht haben, kochen wir das erste Element nicht. Das macht unsere Ausgabe etwas seltsam, also ist es definitiv etwas, worauf man achten sollte. Hier ist, was ich meine.

const wineReduction = ingredients.reduce((sauce, item) => {
  return sauce += cook(item) + ', '
  })
  
// wineReduction = "winecooked tomato, cooked onion, cooked mushroom, "

Um sicherzustellen, dass wir am Ende unserer neuen Zeichenkette keine überschüssigen Leerzeichen haben, können wir den Index und das Array übergeben, um unsere Transformation anzuwenden.

const wineReduction = ingredients.reduce((sauce, item, index, array) => {
  sauce += cook(item)
  if (index < array.length - 1) {
        sauce += ', '
        }
        return sauce
  }, '')
  
// wineReduction = "cooked wine, cooked tomato, cooked onion, cooked mushroom"

Jetzt können wir dies noch prägnanter (in einer einzigen Zeile!) schreiben, indem wir ternäre Operatoren, Zeichenfolgen-Vorlagen und implizite Rückgaben verwenden.

const wineReduction = ingredients.reduce((sauce, item, index, array) => {
  return (index < array.length - 1) ? sauce += `${cook(item)}, ` : sauce += `${cook(item)}`
}, '')

// wineReduction = "cooked wine, cooked tomato, cooked onion, cooked mushroom"

Eine kleine Eselsbrücke, um sich dies zu merken, ist, sich daran zu erinnern, wie man Sauce macht: Man **reduziert** ein paar Zutaten zu einem einzigen Gegenstand.

Sing it with me! (Singen Sie mit mir!)

Ich wollte diesen Blogbeitrag mit einem Lied beenden, also habe ich ein kleines Liedchen über Array-Methoden geschrieben, das Ihnen vielleicht helfen könnte, sich diese zu merken.