
.NET 3.5+LINQ Aggregation
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.
Aggregation Standard Query Operators
LINQ provides a number of aggregation operators. These are standard query operators, all extension methods of the IEnumerable<T> interface, that perform a calculation across all of the values in a collection. For example, you can use aggregate operators to count the number of items in a sequence or to sum a set of numeric values. All of the methods can be used to aggregate all of the items in a sequence, or with the GroupBy operator to calculate aggregate values for a number of groups.
To demonstrate the operators we need a class and some sample data. The class will hold the details of a stock item, including a name, category and price. The code is as follows:
public class StockItem
{
public string Name { get; set; }
public string Category { get; set; }
public double Price { get; set; }
public StockItem(string name, string category, double price)
{
Name = name;
Category = category;
Price = price;
}
}
To create a list of sample stock items, add the following code:
var stock = new List<StockItem>
{
new StockItem("Apple", "Fruit", 0.30),
new StockItem("Banana", "Fruit", 0.35),
new StockItem("Orange", "Fruit", 0.29),
new StockItem("Cabbage", "Vegetable", 0.49),
new StockItem("Carrot", "Vegetable", 0.29),
new StockItem("Lettuce", "Vegetable", 0.30),
new StockItem("Milk", "Dairy", 1.12)
};
Count
The first of the aggregation standard query operators that we will consider is Count. This simple method returns the number of items in a sequence, in a similar manner to the Count property supported by collections that implement the ICollection interface. The return value is an integer.
var count = stock.Count(); // count = 7
Aggregate operators are often used with grouped data. In the following example the stock items are grouped according to their categories. The results are returned as a set of anonymous types, each containing a category name and the number of items within that category:
var groupCounts = stock.GroupBy(s => s.Category, (c, i) => new { Category = c, Count = i.Count() });
/* RESULTS
{ Category = Fruit, Count = 3 }
{ Category = Vegetable, Count = 3 }
{ Category = Dairy, Count = 1 }
*/
The Count method has an overloaded version that accepts a Func delegate, usually a lambda expression, that acts as a predicate. This allows you to count the number of items that meet certain conditions. In the code below, the predicate returns true when the price of an item is greater than 0.3. This means that only stock items with a price of over 0.3 are counted for each category:
var groupCounts = stock.GroupBy(s => s.Category, (c, i) => new { Category = c, Count = i.Count(s => s.Price > 0.3) });
/* RESULTS
{ Category = Fruit, Count = 1 }
{ Category = Vegetable, Count = 1 }
{ Category = Dairy, Count = 1 }
*/
12 August 2010