
.NET 3.5+LINQ Aggregation (2)
The seventh part of the LINQ to Objects tutorial looks at aggregate functions. These are standard query operators that can be applied to sequences and groups, performing a calculation that combines all of the values in a collection.
LongCount
The LongCount operator is almost identical to Count. It can be used for entire sequences or for groups, and can include a predicate that determines which items to count. The key difference is that the result is a long, rather than a standard integer.
var groupCounts = stock.GroupBy(s => s.Category,
(c, i) => new { Category = c, Count = i.LongCount(s => s.Price > 0.3) });
/* RESULTS
{ Category = Fruit, Count = 1 }
{ Category = Vegetable, Count = 1 }
{ Category = Dairy, Count = 1 }
*/
Sum
The Sum method totals the values in a sequence. When used with a collection that contains only numeric values, the method can be used with no arguments. In the sample below, the values in an array of integers are summed:
var sum = new int[] { 1, 2, 3, 4 }.Sum(); // sum = 10
If you are working with non-numeric types, an overloaded version of Sum can be used. This overload accepts a single parameter containing a Func delegate that returns the values to sum, known as a selector function. This is demonstrated in the example below, which groups the stock items by category and sums the prices in each group. The lambda expression, "s => s.Price" is used to return each price.
var groupSums = stock.GroupBy(s => s.Category,
(c, i) => new { Category = c, Sum = i.Sum(s => s.Price) });
/* RESULTS
{ Category = Fruit, Sum = 0.94 }
{ Category = Vegetable, Sum = 1.08 }
{ Category = Dairy, Sum = 1.12 }
*/
NB: if the sequence of values contains no items, the sum will be zero.
Max and Min
The Max and Min standard query operators return the largest and smallest values in a sequence respectively. As with Sum, these operators can be used without parameters for numeric sequences or with a Func delegate parameter that returns the values to be compared.
var groupMaxMin = stock.GroupBy(s => s.Category, (c, i) => new
{
Category = c,
Max = i.Max(s => s.Price),
Min = i.Min(s => s.Price)
});
/* RESULTS
{ Category = Fruit, Max = 0.35, Min = 0.29 }
{ Category = Vegetable, Max = 0.49, Min = 0.29 }
{ Category = Dairy, Max = 1.12, Min = 1.12 }
*/
12 August 2010