Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort and Group in LINQ

Tags:

c#

linq

grouping

I have a list of string tuples, say (P1,P2)

I'd like to know if there's a LINQ statement where I could group by P1 (in ascending order), and have that group contain all the P2 values for the group (in descending order).

For input: ("A","B"), ("A","C"), ("D","B") I'd like to get two groups: "A" and "D" (in that order, every time) where group "A" contains "C" and "B" (in that order, every time) and group "D" contains, well, "B".

Is this possible with the built-in LINQ classes or do I need to iterate the groups and sort them myself?

like image 324
Jono Avatar asked Apr 27 '10 19:04

Jono


People also ask

How do I sort by group in C#?

GroupBy(student => student.Name) . Select(group => new { Name = group. Key, Students = group. OrderByDescending(x => x.

What is GroupBy in LINQ?

Grouping is a very powerful feature provided by LINQ that transforms a collection in groups where each group has a key associated with it. Note: GroupBy performs a deferred execution which means the query is only executed when the records are processed using a foreach loop.

Does LINQ GroupBy keep order?

Found answer on MSDN: Yes.

What is LINQ SQL class?

LINQ to SQL - ADO.NET LINQ to SQL is a component of the . NET Framework that provides a run-time infrastructure for managing relational data as objects.


1 Answers

Nope, it's not hard - you just need to keep track of whether you're looking at a group or elements within the group. Here's a sample query:

var query = from tuple in tuples
            orderby tuple.P1
            group tuple.P2 by tuple.P1 into g
            select new { Group = g.Key,
                         Elements = g.OrderByDescending(p2 => p2) };

Here's a complete example (avoiding .NET 4's Tuple type just for simplicity if you're using .NET 3.5):

using System;
using System.Collections.Generic;
using System.Linq;

public class MyTuple
{
    public string P1 { get; set; }
    public string P2 { get; set; }
}

class Test
{
    static void Main()
    {
        List<MyTuple> tuples = new List<MyTuple>
        {
            new MyTuple { P1 = "A", P2 = "B" },
            new MyTuple { P1 = "A", P2 = "C" },
            new MyTuple { P1 = "D", P2 = "B" },
        };

        var query = from tuple in tuples
            orderby tuple.P1
            group tuple.P2 by tuple.P1 into g
            select new { Group = g.Key,
                         Elements = g.OrderByDescending(p2 => p2) };

        foreach (var group in query)
        {
            Console.WriteLine("{0}:", group.Group);
            foreach (var value in group.Elements)
            {
                Console.WriteLine("  {0}", value);
            }
        }
    }
}

Note that it can be slightly simpler if you're happy to do the ordering on a "need to know" basis:

var query = from tuple in tuples
    orderby tuple.P1
    group tuple.P2 by tuple.P1;

foreach (var group in query)
{
    Console.WriteLine("{0}:", group.Key);
    foreach (var value in group.OrderByDescending(x => x))
    {
        Console.WriteLine("  {0}", value);
    }
}
like image 50
Jon Skeet Avatar answered Oct 02 '22 12:10

Jon Skeet