The Many Ways to Call Linq GroupBy

By Endy Tjahjono. Last update 25 Jun 2013.

I keep forgetting Linq’s GroupBy syntaxes. Maybe if I write it down I will remember it better.

First, let’s set up the playing field.

public class Order
{
    public Customer Customer { get; set; }
    public List<OrderItem> Items { get; set; }
}

public class OrderItem
{
    public Product Product { get; set; }
    public long Quantity { get; set; }
    public long UnitPrice { get; set; }
}

public class Product
{
    public string Name { get; set; }
}

public class Customer
{
    public string Name { get; set; }
}

From the data structure above, I want to get a list of customers (non repeating) with the total sales of each customer.

I see that there are 3 general ways to call GroupBy:

Let’s try the easiest way first: just tell GroupBy how to divide the collection into groups.

var orders = new List<Order>();

var justSplitIntoGroups = orders.GroupBy(
    o => o.Customer
).Select(
    g => new
    {
        customer = g.Key,
        sales = g.Sum(
            o => o.Items.Sum(
                i => i.Quantity * i.UnitPrice
            )
        )
    }
);

Another way: tell GroupBy to first transform the original collection.

var splitAndTransformOriginal = orders.GroupBy(
    o => o.Customer,
    o => o.Items.Sum(
        i => i.Quantity * i.UnitPrice
    )
).Select(
    g => new
    {
        customer = g.Key,
        sales = g.Sum()
    }
);

Another way: tell GroupBy how to construct the end result.

var splitAndReduce = orders.GroupBy(
    o => o.Customer,
    (cust, ordrs) => new
    {
        customer = cust,
        sales = ordrs.Sum(
            o => o.Items.Sum(
                i => i.Quantity * i.UnitPrice
            )
        )
    }
);

The completest approach: tell GroupBy how to transform the original collection and how to construct the end result.

var splitTransformReduce = orders.GroupBy(
    o => o.Customer,
    o => o.Items.Sum(
        i => i.Quantity * i.UnitPrice
    ),
    (cust, sls) => new
    {
        customer = cust,
        sales = sls.Sum()
    }
);

comments powered by Disqus