Seskupování pomocí Array.prototype.groupBy

Od doby, kdy jsem začal programovat, jsem se vždy dostal do situací, kdy jsem potřeboval použít jednoduchou funkci, ale zároveň neexistující v jazycích, na kterých jsem pracoval.

Nejinak tomu bylo, když jsem musel pracovat s JavaScriptem a potřeboval jsem udělat jednoduchou akci seskupení, to znamená, že jsem musel rozdělit svůj objekt nebo pole do malých skupin podle typu položky, kterou jsem v nich měl.

Naštěstí jednou ze spásy každého vývojáře, když potřebuje používat velmi běžné funkce, je uchýlit se ke knihovnám nástrojů, dnes nejznámější je LoDash, který má shodou okolností metodu nazvanou groupBy .

Ale věk stahování externích knihoven pro tyto jednoduché funkce je pryč, protože nyní můžeme mít vlastní groupBy , pouze nativní.

Skupina

Seskupovací funkce spadají do třídy funkcí, které rád nazývám úžasné a líné , protože tyto funkce jsou extrémně užitečné pro téměř všechny druhy věcí, které můžeme ve vývoji dělat, přičemž jsou rychlé a jednoduché na implementaci, ale jsou tak jednoduché, že zároveň nestojí za to psát něco od začátku.

To je důvod, proč se mnoho lidí uchýlí ke stažení externí knihovny, jako je LoDash, aby byl problém vyřešen jednoduchým a praktickým způsobem.

Nikdy jsem nebyl velkým fanouškem toho, že bych si musel stáhnout knihovnu a vytvořit závislost na externím kódu pro tak jednoduchou funkci, zvláště pokud ji ve svém kódu použiji pouze jednou. Takže raději dělám tyto funkce ručně.

Existuje nekonečně mnoho způsobů, jak můžete provádět jednoduché seskupování, a jednoduchým seskupováním mám na mysli schopnost vzít řadu položek v rámci pole a uspořádat je do kategorií, například oddělit uživatele v systému podle úrovně přístupu:

const usuarios = [
    { name: 'Lucas', role: 'admin' },
    { name: 'Ana', role: 'reader' },
    { name: 'Erick', role: 'reader' },
    { name: 'Beatriz', role: 'writer' },
    { name: 'Carla', role: 'admin' }
]

Výstup, který chci, je něco takového:

const groups = {
    admin: [
        {name: 'Lucas', role: 'admin'}, 
        {name: 'Carla', role: 'admin'}
    ],
    reader: [
        { name: 'Ana', role: 'reader' },
        { name: 'Erick', role: 'reader' },
    ],
    writer: [
        { name: 'Beatriz', role: 'writer' }
    ]
}

Jak tedy takovou funkci uděláme? Nejjednodušší způsob, který mě napadá, je reduce :

function groupBy (array, key) {
    return array.reduce((acc, item) => {
        if (!acc[item[key]]) acc[item[key]] = []
        acc[item[key]].push(item)
        return acc
    }, {})
}

Existuje další způsob, jak seskupovat, pokud reduce trochu více zjednodušíme použijte operátor spread :

function groupBy (array, key) {
    return array.reduce((acc, item) => ({
      ...acc,
      [item[key]]: [...(acc[item[key]] ?? []), item],
    }),
  {})
}

Existují však články, které komentují, že použití spreadu v tomto případě může být špatný nápad, protože budeme mít „skrytou“ smyčku, díky které se naše funkce stane funkcí exponenciální složitosti.

Pak máme lodash.groupBy, což je téměř stejná implementace, ale s některými typy kvůli kompatibilitě a přísnějšími kontrolami chyb. Funkce, která spolu s dalšími, jako je intersect a difference , jsou úžasní a líní.

Nativní řešení

Nedávno výbor TC39, organizace, která spravuje a řídí JavaScript, oznámil, že jeden z jejich návrhů, ten, který bude obsahovat novou metodu groupBy uvnitř Array.prototype , již dosáhl fáze 3!

To znamená, že brzy uvidíme implementaci přesně jako je tato v kódových systémech po celém světě:

const usuarios = [
    { name: 'Lucas', role: 'admin' },
    { name: 'Ana', role: 'reader' },
    { name: 'Erick', role: 'reader' },
    { name: 'Beatriz', role: 'writer' },
    { name: 'Carla', role: 'admin' }
]

const grouped = usuarios.groupBy(({role}) => role)

Myšlenka je taková, že tato funkce bude vydána jako součást ES2022 během tohoto roku a za chvíli vstoupí jako nedílná součást prohlížečů.

Ale pokud jste jako já a chcete tuto funkci otestovat co nejdříve, pak potřebujete implementační podložku nebo počkejte na použití babel v předvolbě stage-3 takže můžete kódovat stejným způsobem jako dnes!