MWCodebymw.de ↗
JavaScript

Object.groupBy – Listen gruppieren, ohne reduce zu schreiben

„Alle Bestellungen nach Status" war jahrelang ein reduce mit Startwert, Prüfung auf das Fach und push. Seit Object.groupBy ist es eine Zeile – und die liest man auch nach einem halben Jahr noch.

Gruppieren ist eine der häufigsten Aufgaben überhaupt: Bestellungen nach Status, Termine nach Tag, Produkte nach Kategorie. Der klassische Weg sah so aus:

const nachStatus = bestellungen.reduce((acc, b) => {
  (acc[b.status] ||= []).push(b);
  return acc;
}, {});

Funktioniert – aber drei Zeilen Mechanik für einen Gedanken.

Eine Zeile

const nachStatus = Object.groupBy(bestellungen, b => b.status);

// {
//   offen:    [ {…}, {…} ],
//   bezahlt:  [ {…} ],
//   storniert:[ {…} ]
// }

Die Rückgabefunktion liefert den Gruppenschlüssel. Das Ergebnis ist ein Objekt ohne Prototyp (null-Prototyp), damit ein Datensatz mit dem Status constructor oder __proto__ nichts kaputt macht.

Auch für gerechnete Schlüssel

const nachMonat = Object.groupBy(
  termine,
  t => new Date(t.datum).toLocaleDateString('de-DE', { month: 'long', year: 'numeric' })
);

const nachPreisklasse = Object.groupBy(produkte, p =>
  p.preis < 20 ? 'guenstig' : p.preis < 100 ? 'mittel' : 'teuer'
);

Der zweite Parameter der Funktion ist übrigens der Index – praktisch für „jede zweite Zeile":

const zebra = Object.groupBy(zeilen, (_, i) => (i % 2 ? 'ungerade' : 'gerade'));

Map.groupBy, wenn der Schlüssel kein String ist

Object.groupBy wandelt jeden Schlüssel in einen String. Willst du nach einem Objekt, einer Zahl oder einem Datum gruppieren und das auch zurückbekommen, nimm die Map-Variante:

const nachKunde = Map.groupBy(bestellungen, b => b.kunde);   // Schlüssel bleibt das Kundenobjekt
for (const [kunde, liste] of nachKunde) {
  console.log(kunde.name, liste.length);
}

Fallstrick

Zwei Dinge. Erstens: Die Reihenfolge der Gruppen folgt der Reihenfolge des ersten Auftretens – bei numerischen Schlüsseln sortiert ein Objekt sie allerdings aufsteigend, weil JavaScript Integer-Schlüssel so behandelt. Wenn die Reihenfolge zählt, nimm Map.groupBy. Zweitens: Beide Methoden sind verhältnismäßig neu (ES2024). In aktuellen Browsern und in Node ab Version 21 sind sie da; für ältere Ziele hilft ein kleiner Ersatz mit reduce – oder du prüfst vorher typeof Object.groupBy === 'function'.

Sauberes, gut lesbares Frontend gehört zu jedem Projekt, das ich baue. Melde dich über bymw.de.

Quellen

#JavaScript#Arrays#Object.groupBy#Map.groupBy#ES2024

Du brauchst mehr als ein Snippet?

Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.

Projekt anfragen →