'svelte each block grouping results delimma

I have an array called products that contains products. Each product belongs to a category.

 product = { category : "shorts", name : "whatever", ...}

Now when I iterate over that array in svelte, I use each block

{#each products as product}
 <li>
   {product.category} - {product.name}
</li>
{/each}

So my results are like this : shorts - blueshort shorts - greenshort shorts - yellowshort

My question is how to group the display the results by category. Like this

 shorts
          blueshort
          greenshort
          yellowshort
     hats 
          bluehat
          greenhat
          yellowwhatever

Is there a way to do it from the each block or I have to take care of it in the script and then send it to the html?

Is there a way to do that in the each block?



Solution 1:[1]

You can use reduce to group results by category and nested each statements:

<script>
    let products = [
        { category : "shorts", name : "hat one" },
        { category : "shorts", name : "hat two" },
        { category : "hats", name : "hat one" },
        { category : "hats", name : "hat two" },
    ];
    
    // group products by category
    $: data = products.reduce((acc, curr) => {
        // create key and value of array if hasn't been created yet
        if (!acc[curr.category]) acc[curr.category] = [];
        acc[curr.category].push(curr.name);
        return acc;
    }, {});
</script>

<div>
    {#each Object.entries(data) as item}
    <div>{item[0]}</div>
    <ul>
        {#each item[1] as name}
            <li>{name}</li>
        {/each}
    </ul>
    {/each}
</div>

Here is an example in action

Hopefully that helps.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1