Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get one of each

The goal

Get one of each result returned by a foreach.

The scenario

Take a look in the follow Razor's code fragment:

@foreach (var product in Model.Collection.Products)
{
    <p>@product.name</p>
}

The return to the client is:

Xbox 360

Xbox 360

Xbox 360

Xbox 360

Playstation 3

Playstation 3

Playstation 3

Now, let me explain: my application compares the price of products in different stores. In my case, there are Xbox 360 in four stores while Playstation 3 exists in three stores — that's why their names repeat.

What I want is simple: get the name of each product just one time to fill a HTML's table column — can you all understand?

Philosophy

Each product is added on Session. In our case, there are two products on session — the first one is Xbox 360 and the second is Playstation 3. So, as you can see I can use Session to work with this ("for each item on Session, do something..."), but I think it isn't necessary because invariably I'll have to run a query on the database and, by logic, its returns me what I need. In other words, I do not need to use the Session except to temporarily store what the users need.

Spotlight

The Model.Collection.Products is of type List<Products>.

What do I tried?

Something like this:

@foreach (var product in Model.Collection.Products.FirstOrDefault())
{
    [...]
}

But, of course, unsuccessful. Basically I need something like FirstOfEach().

like image 625
Guilherme Oderdenge Avatar asked Aug 06 '13 14:08

Guilherme Oderdenge


1 Answers

The Solution

Use a GroupBy...

@foreach (var group in Model.Collection.Products.GroupBy(x => x.name))
{
    <p>@group.Key</p>
}

A GroupBy will return an IEnumerable<IGrouping<TKey, TSource>> where the Key property represents the value of the property you are grouping by (in this case: name)


Other Benefits

The benefit of this approach is that you can also access the items for each group, so if you wanted to list the different prices for each group, for example, you could do something like this:

@foreach (var group in Model.Collection.Products.GroupBy(x => x.name))
{
    <p>Product: @group.Key (@group.Count() items)</p>
    <p>Prices: 
    @foreach(var item in group)
    {
        <span>@item.price</span>
    }
    </p>
}

(I know this isn't the best HTML, it's just an example of usage!)

like image 56
musefan Avatar answered Sep 20 '22 12:09

musefan