1

I have the following list (simplified):

Name | Brand
Shirt0 | Adidas
Shirt1 | Nike
Shirt2 | Adidas
Shirt3 | Adidas
Shirt4 | Erima
Shirt5 | Nike

I want to order it by Brand, and display (a maximum of) two of a brand in sequence.
Therefore I would not display all 3 Adidas products first, but only two!

Result:

Shirt0 | Adidas
Shirt2 | Adidas
Shirt1 | Nike
Shirt5 | Nike
Shirt4 | Erima
Shirt3 | Adidas

So it takes two products from every brand, and starts over when no more available.

Any ideas how to achieve this with LINQ?

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
tobi.at
  • 1,267
  • 13
  • 18

2 Answers2

2

Using the ideas here you can group the items with each brand into indexes, then order by index and brand and join back into a single list:

var results = products.GroupBy(p => p.Brand)
    .SelectMany(pg => pg.Select((p, index) => new { Value = p, Index = index/2 }))
    .OrderBy(a => a.Index).ThenBy(a => a.Value.Brand)
    .Select(g => g.Value);
Community
  • 1
  • 1
Rhumborl
  • 16,349
  • 4
  • 39
  • 45
  • 1
    Thanks. This is what I was searching for :) @danyloid submitted the same approach (but earlier), therefore I had to give him the checkmark, sorry :-S – tobi.at Oct 28 '14 at 09:46
1

I assume that your Product class has something like the following property:

public String Brand { get; }

I would use the following approach:

  1. Group products by Brand property
  2. Wrap the result in each group in an anonymous class with additional Order property and assign it 0 if the index within the grouping is less than 2 and 1 if else (will apply for the first and second item)
  3. Apply the order based on the Order property of our anonymous class
  4. Select the product, so we get rid of our anonymous wrapper class

The query below:

var result = list
    .GroupBy(x => x.Brand)
    .SelectMany(g => g.Select((x, i) => new { Order = i < 2 ? 0 : 1, Product = x }))
    .OrderBy(x => x.Order)
    .Select(x => x.Product)
    .ToList();

I suppose there may be a better approach, but this one is straight from head.

danyloid
  • 1,677
  • 3
  • 21
  • 47
  • 1
    This is exactly what I was searching for, thanks so much! And produces the same result as the answer from @Rhumborl – tobi.at Oct 28 '14 at 09:45