JavaScript Fortgeschritten

Array-Methoden meistern (map, filter, reduce)

Array-Methoden meistern

map, filter und reduce sind die mächtigsten Werkzeuge für die Arbeit mit Arrays. Wenn du diese Methoden beherrschst, wird dein Code kürzer, lesbarer und eleganter.

Die Big Three: map, filter, reduce

map - Transformieren

map erstellt ein neues Array mit transformierten Elementen:

const zahlen = [1, 2, 3, 4, 5];

// Jede Zahl verdoppeln
const verdoppelt = zahlen.map(zahl => zahl * 2);
console.log(verdoppelt);  // [2, 4, 6, 8, 10]

// Original bleibt unverändert!
console.log(zahlen);  // [1, 2, 3, 4, 5]

Wann verwenden? Wenn du jedes Element transformieren willst und die gleiche Anzahl Elemente behalten willst.

// Strings zu Großbuchstaben
const namen = ["anna", "ben", "clara"];
const gross = namen.map(name => name.toUpperCase());
// ["ANNA", "BEN", "CLARA"]

// Nur bestimmte Eigenschaften extrahieren
const users = [
    { id: 1, name: "Max", email: "max@test.de" },
    { id: 2, name: "Lisa", email: "lisa@test.de" }
];
const emails = users.map(user => user.email);
// ["max@test.de", "lisa@test.de"]

// Objekte transformieren
const preise = [10, 20, 30];
const mitMwSt = preise.map(preis => ({
    netto: preis,
    mwst: preis * 0.19,
    brutto: preis * 1.19
}));

filter - Filtern

filter erstellt ein neues Array mit Elementen, die den Test bestehen:

const zahlen = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Nur gerade Zahlen
const gerade = zahlen.filter(zahl => zahl % 2 === 0);
console.log(gerade);  // [2, 4, 6, 8, 10]

// Größer als 5
const gross = zahlen.filter(zahl => zahl > 5);
console.log(gross);  // [6, 7, 8, 9, 10]

Wann verwenden? Wenn du Elemente basierend auf einer Bedingung aussortieren willst.

// Aktive User filtern
const users = [
    { name: "Max", active: true },
    { name: "Lisa", active: false },
    { name: "Tom", active: true }
];
const aktive = users.filter(user => user.active);
// [{ name: "Max", active: true }, { name: "Tom", active: true }]

// Leere Strings entfernen
const texte = ["Hallo", "", "Welt", "", "!"];
const nichtLeer = texte.filter(text => text !== "");
// ["Hallo", "Welt", "!"]

// Truthy-Werte behalten (kürzeste Variante)
const gemischt = [0, 1, "", "Hallo", null, undefined, false, true];
const truthy = gemischt.filter(Boolean);
// [1, "Hallo", true]

reduce - Reduzieren

reduce reduziert ein Array auf einen einzelnen Wert:

const zahlen = [1, 2, 3, 4, 5];

// Summe berechnen
const summe = zahlen.reduce((accumulator, current) => {
    return accumulator + current;
}, 0);

console.log(summe);  // 15

// Kurzform
const summe2 = zahlen.reduce((acc, curr) => acc + curr, 0);

Anatomie von reduce:

array.reduce((accumulator, currentValue, index, array) => {
    // accumulator = bisheriges Ergebnis
    // currentValue = aktuelles Element
    // return = neuer accumulator
}, initialValue);

Wann verwenden? Wenn du alle Elemente zu einem Wert kombinieren willst.

// Produkt aller Zahlen
const zahlen = [1, 2, 3, 4, 5];
const produkt = zahlen.reduce((acc, curr) => acc * curr, 1);
// 120

// Maximum finden
const max = zahlen.reduce((a, b) => a > b ? a : b);
// 5

// Gesamtpreis berechnen
const warenkorb = [
    { name: "Buch", preis: 15, menge: 2 },
    { name: "Stift", preis: 2, menge: 5 },
    { name: "Block", preis: 5, menge: 1 }
];

const gesamt = warenkorb.reduce((summe, item) => {
    return summe + (item.preis * item.menge);
}, 0);
// 15*2 + 2*5 + 5*1 = 45

Reduce für komplexe Operationen

Array zu Objekt

const paare = [["name", "Max"], ["alter", 25], ["stadt", "Berlin"]];

const objekt = paare.reduce((obj, [key, value]) => {
    obj[key] = value;
    return obj;
}, {});

console.log(objekt);
// { name: "Max", alter: 25, stadt: "Berlin" }

Gruppieren

const personen = [
    { name: "Max", abteilung: "IT" },
    { name: "Lisa", abteilung: "HR" },
    { name: "Tom", abteilung: "IT" },
    { name: "Anna", abteilung: "HR" }
];

const nachAbteilung = personen.reduce((gruppen, person) => {
    const abt = person.abteilung;
    if (!gruppen[abt]) {
        gruppen[abt] = [];
    }
    gruppen[abt].push(person);
    return gruppen;
}, {});

console.log(nachAbteilung);
// {
//   IT: [{ name: "Max", ... }, { name: "Tom", ... }],
//   HR: [{ name: "Lisa", ... }, { name: "Anna", ... }]
// }

Häufigkeiten zählen

const buchstaben = ["a", "b", "a", "c", "b", "a"];

const haeufigkeit = buchstaben.reduce((count, buchstabe) => {
    count[buchstabe] = (count[buchstabe] || 0) + 1;
    return count;
}, {});

console.log(haeufigkeit);
// { a: 3, b: 2, c: 1 }

Flatten (Array platt machen)

const nested = [[1, 2], [3, 4], [5, 6]];

const flat = nested.reduce((acc, curr) => [...acc, ...curr], []);
console.log(flat);  // [1, 2, 3, 4, 5, 6]

// Oder einfacher mit flat()
const flat2 = nested.flat();

Weitere wichtige Methoden

find - Erstes Element finden

const users = [
    { id: 1, name: "Max" },
    { id: 2, name: "Lisa" },
    { id: 3, name: "Tom" }
];

const user = users.find(u => u.id === 2);
console.log(user);  // { id: 2, name: "Lisa" }

// Nicht gefunden = undefined
const notFound = users.find(u => u.id === 99);
console.log(notFound);  // undefined

findIndex - Index finden

const zahlen = [10, 20, 30, 40, 50];

const index = zahlen.findIndex(z => z > 25);
console.log(index);  // 2 (weil 30 > 25)

// Nicht gefunden = -1
const notFound = zahlen.findIndex(z => z > 100);
console.log(notFound);  // -1

some - Mindestens einer

const zahlen = [1, 2, 3, 4, 5];

const hatGerade = zahlen.some(z => z % 2 === 0);
console.log(hatGerade);  // true

const hatNegative = zahlen.some(z => z < 0);
console.log(hatNegative);  // false

every - Alle

const zahlen = [2, 4, 6, 8, 10];

const alleGerade = zahlen.every(z => z % 2 === 0);
console.log(alleGerade);  // true

const allePositiv = zahlen.every(z => z > 0);
console.log(allePositiv);  // true

includes - Enthält

const fruechte = ["Apfel", "Banane", "Orange"];

console.log(fruechte.includes("Banane"));  // true
console.log(fruechte.includes("Mango"));   // false

Methoden verketten

Die wahre Macht liegt im Verketten (Chaining):

const users = [
    { name: "Max", alter: 17, active: true },
    { name: "Lisa", alter: 25, active: true },
    { name: "Tom", alter: 30, active: false },
    { name: "Anna", alter: 22, active: true },
    { name: "Ben", alter: 16, active: true }
];

// Alle aktiven User über 18, sortiert nach Alter, nur Namen
const ergebnis = users
    .filter(user => user.active)           // Nur aktive
    .filter(user => user.alter >= 18)      // Über 18
    .sort((a, b) => a.alter - b.alter)     // Nach Alter sortieren
    .map(user => user.name);               // Nur Namen

console.log(ergebnis);  // ["Anna", "Lisa"]

Praktisches Beispiel: E-Commerce

const produkte = [
    { name: "Laptop", preis: 999, kategorie: "Elektronik", lager: 5 },
    { name: "Maus", preis: 29, kategorie: "Elektronik", lager: 50 },
    { name: "Buch", preis: 15, kategorie: "Bücher", lager: 0 },
    { name: "Tastatur", preis: 79, kategorie: "Elektronik", lager: 20 },
    { name: "Roman", preis: 12, kategorie: "Bücher", lager: 30 }
];

// Verfügbare Elektronik-Produkte unter 100€, sortiert nach Preis
const guenstigeElektronik = produkte
    .filter(p => p.kategorie === "Elektronik")
    .filter(p => p.lager > 0)
    .filter(p => p.preis < 100)
    .sort((a, b) => a.preis - b.preis)
    .map(p => `${p.name}: ${p.preis}€`);

console.log(guenstigeElektronik);
// ["Maus: 29€", "Tastatur: 79€"]

// Gesamtwert des Lagers
const lagerWert = produkte.reduce((summe, p) => {
    return summe + (p.preis * p.lager);
}, 0);

console.log(`Lagerwert: ${lagerWert}€`);

flatMap

flatMap = map + flat(1):

const saetze = ["Hallo Welt", "Wie geht es dir"];

// Mit map + flat
const worte1 = saetze.map(s => s.split(" ")).flat();

// Mit flatMap (eleganter)
const worte2 = saetze.flatMap(s => s.split(" "));

console.log(worte2);  // ["Hallo", "Welt", "Wie", "geht", "es", "dir"]
// Alle Freunde aller User
const users = [
    { name: "Max", freunde: ["Lisa", "Tom"] },
    { name: "Lisa", freunde: ["Max", "Anna"] }
];

const alleFreunde = users.flatMap(u => u.freunde);
console.log(alleFreunde);  // ["Lisa", "Tom", "Max", "Anna"]

// Unique Freunde
const uniqueFreunde = [...new Set(alleFreunde)];
console.log(uniqueFreunde);  // ["Lisa", "Tom", "Max", "Anna"]

Häufige Patterns

Duplikate entfernen

const mitDuplikaten = [1, 2, 2, 3, 3, 3, 4];

// Mit Set (einfachste Methode)
const unique = [...new Set(mitDuplikaten)];

// Mit filter
const unique2 = mitDuplikaten.filter((item, index, array) => {
    return array.indexOf(item) === index;
});

console.log(unique);  // [1, 2, 3, 4]

Differenz zweier Arrays

const arr1 = [1, 2, 3, 4, 5];
const arr2 = [3, 4, 5, 6, 7];

// In arr1 aber nicht in arr2
const differenz = arr1.filter(x => !arr2.includes(x));
console.log(differenz);  // [1, 2]

// In beiden
const schnittmenge = arr1.filter(x => arr2.includes(x));
console.log(schnittmenge);  // [3, 4, 5]

// Vereinigung (unique)
const vereinigung = [...new Set([...arr1, ...arr2])];
console.log(vereinigung);  // [1, 2, 3, 4, 5, 6, 7]

Top N Elemente

const scores = [85, 92, 78, 95, 88, 91, 76, 89];

// Top 3
const top3 = [...scores]
    .sort((a, b) => b - a)
    .slice(0, 3);

console.log(top3);  // [95, 92, 91]

Objekte nach Wert sortieren

const scores = { Max: 85, Lisa: 92, Tom: 78, Anna: 95 };

// Als sortiertes Array
const sortiert = Object.entries(scores)
    .sort((a, b) => b[1] - a[1])
    .map(([name, score]) => `${name}: ${score}`);

console.log(sortiert);
// ["Anna: 95", "Lisa: 92", "Max: 85", "Tom: 78"]

Performance beachten

// ❌ Schlecht: Mehrfache Iteration
const ergebnis = arr
    .filter(x => x > 10)
    .filter(x => x < 100)
    .filter(x => x % 2 === 0);

// ✅ Besser: Eine Iteration
const ergebnis2 = arr.filter(x => x > 10 && x < 100 && x % 2 === 0);

// ❌ Schlecht: map + filter wenn nur filter nötig
const gefiltert = arr
    .map(x => x * 2)
    .filter(x => x > 10);

// ✅ Besser: Bedingung vor Transformation prüfen
const gefiltert2 = arr
    .filter(x => x * 2 > 10)  // Oder: x > 5
    .map(x => x * 2);

Zusammenfassung

MethodeRückgabeZweck
mapArray (gleiche Länge)Transformieren
filterArray (≤ Länge)Filtern
reduceEinzelwertKombinieren
findElement oder undefinedErstes finden
findIndexIndex oder -1Index finden
someBooleanMind. einer?
everyBooleanAlle?
includesBooleanEnthält?
flatMapArraymap + flatten
// Merksatz:
// map    → transformiere jedes Element
// filter → behalte passende Elemente
// reduce → kombiniere zu einem Wert
// find   → finde das erste passende

Übung: Gegeben ist ein Array von Bestellungen. Berechne: 1) Gesamtumsatz, 2) Durchschnittlicher Bestellwert, 3) Top 3 Produkte nach Umsatz

const bestellungen = [
    { produkt: "Laptop", preis: 999, menge: 2 },
    { produkt: "Maus", preis: 29, menge: 10 },
    { produkt: "Tastatur", preis: 79, menge: 5 },
    { produkt: "Laptop", preis: 999, menge: 1 },
    { produkt: "Monitor", preis: 349, menge: 3 }
];