2

I am trying to use IComprarer to a complex sort. I have this complex type (for sake of simplicity, three ints):

ID | A | B
1  | 1 | 10
2  | 3 | 20
3  | 1 | 30
4  | 3 |  5
5  | 2 | 15

And i need to Sort by B, but i need to keep A together. B can be ASC or DESC but I can not separate 'A'

It must order this way:

ID | A | B
3  | 1 | 30
1  | 1 | 10
2  | 3 | 20
4  | 3 |  5
5  | 2 | 15

There are NOTHING special in A order, the important things are: B is ordered and the same A must not be separated.

I tried:

public int Compare(Comanda x, Comanda y)
{
    if (x.A == y.A) return 0;
    return x.B.CompareTo(y.B);
}

But does not work and I even don't know HOW to ask it to google, "group" keyword do not help much.

And also tried to sort twice which, obviously doesn't work (discarded the B order).

list.Sort(new SortByB());
list.Sort(new SortByA());

How can I do it ? Thanks

This is not a duplicate of "C# List<> Sort by x then y" bucause i don't want do double-sort. I wanted to GROUP

ekad
  • 14,436
  • 26
  • 44
  • 46
Rafael
  • 345
  • 3
  • 16
  • It looks like you want to group by A, then order on the max B in each grouping and also order the items in the groups by B. That cannot be done with an `IComparer`. – juharr Oct 19 '16 at 13:15
  • Possible duplicate of [C# List<> Sort by x then y](http://stackoverflow.com/questions/289010/c-sharp-list-sort-by-x-then-y) – Sebi Oct 19 '16 at 13:49
  • @Sebi it is not. I don't want double-sort, I wanted GROUP then sort – Rafael Oct 19 '16 at 15:01

2 Answers2

4

For the specific example I would do the following.

var sorted = list.GroupBy(x => x.A)
            .OrderByDescending(g => g.Max(x => x.B))
            .SelectMany(g => g.OrderByDescending(x => x.B));

You basically need to group on A first then order the groups on the max value of B, then order the items in each group on B.

Another option would be to first order on B, then group on A, then order the groups on the value of B in the first item in the group (which should be the max B for the group since we already ordered on them), then just flatten the results.

var sorted = list.OrderByDescending(x => x.B)
            .GroupBy(x => x.A)
            .OrderByDescending(g => g.First().B)
            .SelectMany(g => g);
juharr
  • 31,741
  • 4
  • 58
  • 93
  • Saved my day ! Thank you so much ! (i didn't know GroupBy and SelectMany, i will read more about it) – Rafael Oct 19 '16 at 13:28
0

You can use orderby i guess:

var sorted = list.orderby(comanda=>commanda.B).thenby(comanda=>commanda.A);
Sebi
  • 3,879
  • 2
  • 35
  • 62