1

I have a problem with a Linq query. I have a query formatted like the following which returns a result set that is grouped by the top level and is ordered by the top level strings alphabetically. I want to return a result set that is ordered by both the top level strings (so the group by clause is ordered alphabetically) and the sub level strings are also in alphabetical order (so each sub group is also alphabetical). What I'm expecting is something like the following:

  • A
    • A
    • B
    • C
  • B
    • A
    • B
    • C

My query is something like the following:

records.results
       .Where(table => string.Compare(table, expected) == 0)
       .OrderByDescending(table => table.name)
       .GroupBy(table => table.name);
       .OrderBy(group => group.Key);

I expect the OrderByDescending statement to change the ordering of the individual records in the groupby clause but it isn't effecting anything. I am receiving ordered results for the groups though. Any help is appreciated!

nobody
  • 7,803
  • 11
  • 56
  • 91

1 Answers1

3

Your problem is that your final OrderBy statement is ordering the groups themselves. What you want to do is order the elements of each group. Try:

   records.results
     .Where(table => string.Compare(table, expected) == 0)
     .OrderByDescending(table => table.name)
     .GroupBy(table => table.name);
     .Select(g => g.OrderByDescending(element => element.Name);

I'm not sure of the name of the property by which you want to order the groups is, but here I'm assuming it is Name.

The key here is to remember that IGrouping is itself an IEnumerable. See the documentation of IGrouping here and note that it implements IEnumerable, so we can call OrderByDescending on each group in your IEnumerable of IGroupings, which is the return type of Enumerable.GroupBy(documented here).

Since OrderByDescending will return an IEnumerable (instead of an IGrouping), this operation will lose the Key property on each group. If you need that, then you might want to simply select an anonymous type to keep the key. Replace the final Select with:

 .Select(g => new { g.Key, elements = g.OrderByDescending(element => element.Name) });

Alternatively, you could write some logic that would intantiate an IGrouping here by following the directions here.

Community
  • 1
  • 1
Ben Reich
  • 16,222
  • 2
  • 38
  • 59
  • Note that the last select loses the `Key` property of the group. If that's needed you may need to stick both the query you have and that key value into a new (possibly anonymous) object. If you don't need the key, then this is just fine. – Servy Jun 07 '13 at 17:23
  • @Servy Good call. I've added a note about that. – Ben Reich Jun 07 '13 at 17:26