LINQ has aggregate operators or methods that allows you to perform mathematical calculations based on the values of all the elements in a collection. We will learn here the different aggregate operators that will simplify the way you do most common tasks involving sets or collections of values. An example of what aggregate operators can do is automatically getting the sum, average, min, max, and how many elements a collection has.

The Count and LongCount Methods


We can determine the number of elements a collection or array has by using the Count and LongCount methods. The Count method simply counts the number of elements of a collection. For collections containing a huge number of elements, we can use the LongCountmethod instead. The following example shows the use of the Count operator.

int[] numbers = { 7, 2, 6, 1, 7, 4, 2, 5, 1, 2, 6 };

Console.WriteLine("numbers has {0} elements.", numbers.Count());

An overload of both Count and LongCount allows you to pass a predicate that will determine which elements to include in the counting. Consider the following example:

Console.Write("Number of even numbers in the collection: {0}", 
              numbers.Count(n => n % 2 == 0));

The lambda expression inside the overloaded Count method specifies the condition that an element must meet for it to be included in the counting.

The Min and Max Methods


The Min and Max method returns the minimum and maximum values from a collection respectively. The parameterless versions of this method are very simple and returns the expected results.

int[] numbers = { 7, 2, 6, 1, 7, 4, 2, 5, 1, 2, 6 };

Console.WriteLine("Min = {0}
Max = {1}", numbers.Min(), numbers.Max());

For complex objects that does has no implementation for IComparable, that is, a default behavior when being compared, we can use an overloaded of the Min() and Max() methods which accept a predicate that specifies the key or expression to be used.

List<Person> people = GetPersonList(); //Assume the method returns a collection of Person objects

Console.WriteLine("Youngest Age is {0}", people.Min( p=>p.Age ));
Console.WriteLine("Oldest Age is {0}", people.Max( p=>p.Age ));

We passed a lambda expression specifying that we should use the Age property of each person as a key and therefore, the Min and Maxmethods returned the minimum and maximum age of all the persons in the collection.

The Average Method


The Average method is obviously used for determining the average of numeric values. The average is the sum of all the values of every element divided by the number of elements.

int[] numbers = { 7, 2, 6, 1, 7, 4, 2, 5, 1, 2, 6 };

Console.WriteLine("Average = {0}", numbers.Average());

Like Min and Max methods, the Average method has an overloaded version which accepts a predicate to determine which key to use when obtaining the average of a complex object such as our example Person class.

List<Person> people = GetPersonList();

Console.WriteLine("Average age of all the persons");
Console.WriteLine("Average = {0}", people.Average( p => p.Age ));

The lambda expression states that we use the Age of every person as the key on getting the average value. Therefore, the method Average results to the average Age of all the persons in the collection.

The Sum Method


The Sum method is also a very simple to understand operator which simply gets the overall sum of all the values of elements in a collection.

int[] numbers = { 7, 2, 6, 1, 7, 4, 2, 5, 1, 2, 6 };

Console.WriteLine("Sum = {0}", numbers.Sum);

Again, we can use an overloaded version which accepts a predicate that will determine a key from a complex object such as Person.

List<Person> people = GetPersonList();

Console.WriteLine("Total age of all the persons");
Console.WriteLine("Total = {0}", people.Sum(p => p.Age));

The expression inside the Sum method instructs the method to add the age of every person together.

The Aggregate Method


The Aggregate method is a more flexible version of method Sum. Instead of limiting you to just summing up values in a collection, you can define a predicate with two parameters, the first one being the firstnumber or the previous result, and the second one is the second or next number to participate the calculation.

int[] numbers = { 1, 2, 3, 4, 5 };

Console.WriteLine(numbers.Aggregate( (n1, n2) => n1 + n2 ));

The Aggregate method contains a two-parameter lambda expression and inside its body, we add the two numbers. Initially, n1 will contain the first value of the array, and n2 will have the second value. It will be added and stored to n1. The next value (third value) will then be stored to n2, and will be added again to n1 whose result will be stored to n1 and n2 acquiring the value of the next element. This repeats until n2 has the value of the last element.

The result of the above call to Aggregate is similar to Sum method since we add every number. A great thing about the Aggregatemethod is we can choose the operator we want on the calculation. Below is a modification of the previous code where the Aggregatereturns the overall product of the collection using the multiplication operator.

int[] numbers = { 1, 2, 3, 4, 5 };

Console.WriteLine( numbers.Aggregate( (n1, n2) => n1 * n2 ) );

You can even create complex expressions like this.

int[] numbers = { 1, 2, 3, 4, 5 };

Console.WriteLine( numbers.Aggregate( (n1, n2) => (n1 / 2) + (n2 / 2) ) );

The Aggregate method above halves the values before adding them to each other. Another overload of the Aggregate method accepts a seed which is simply the one that will take the first slot in the calculation.

int[] numbers = { 1, 2, 3, 4, 5 };

Console.WriteLine( numbers.Aggregate( 1, (n1 , n2) => n1 + n2 ));

Notice that Aggregate now has two parameters, the first one being the seed and the second one is the predicate specifying how to process each pair of values. Since we specified a seed of 1, the calculation will start at 1 plus whatever the first value of the array is. Since the first value of the array in the code above is 1 and the specified seed is 1, then the first calculation will be 1 + 1 (seed + first).

A third overload of the Aggregate method accepts a third argument which specifies the formatting of the result.

Console.WriteLine( numbers.Aggregate( 1, (n1, n2) => n1 + n2, 
                                      n => String.Format("{0:C}", n)));

The third parameter is another lambda expression that will format the result into currency format.

Using these aggregate methods is a great help for programmers as it saves development time and is really easy to use once you mastered them.