LINQ allows you to query for aggregates too. By default, it adds a few extended methods for calculating aggregates to all collections. Let’s return to our array of integers, the data array. To calculate the count of all values, call the Count method of the data array. The count of elements in the data array is given with the following expression:
Dim count = data.Count
Of course, the Array class doesn’t provide a Count method, so where did it come from? Count, as well as a number of other methods, is an extended method. An extended method is added to a class without having to inherit the original class and create a derived class (as you recall, the array cannot even be inherited). The Framework allows you to add methods to a class by extending it, and this technique is used heavily by LINQ.
In addition to the Count method, any LINQ-capable class exposes the Sum method, which sums the values of a specific element or attribute in the collection. To calculate the sum of the selected values from the data array, use the following LINQ expression:
Dim sum = From n data _
Where n > 10
You can also calculate arbitrary aggregates by using the Aggregate method, which accepts as an argument a lambda expression. This expression, in turn, accepts two arguments: the current value and the aggregate. The implementation of the function calculates the aggregate. Let’s consider a lambda expression that calculates the sum of the squares over a sequence of numeric values. The declaration of the function is as follows:
Its implementation is shown here:
aggregate + value ˆ 2
To calculate the sum of the squares of all items in the data array, use the following LINQ expression:
Dim sumSquares = data.Aggregate( _
Function(sumSquare As Long, n As Integer) _
sumSquare + n ˆ 2
The single statement that implements the aggregate adds the square of the current element to the sumSquare argument. When we’re done, the sumSquare variable holds the sum of the squares of the array’s elements. Aggregates are not limited to numeric values. Here’s an interesting example of a LINQ expression that reverses the words in a sentence. The code starts by splitting the sentence into words, which are returned in an array of strings. Then it calls the Aggregate method, passing as an argument a lambda expression. This expression is a function that prefixes the aggregate (the string with words in reverse order) with the current word:
Dim sentence = _
"The quick brown fox jumped over the lazy dog"
Dim reverseSentence = _
sentence.Split(" ".c).Aggregate( _
Function (newSentence, word) _
word & " " & newSentence
A few more interesting extended methods are the following:
Take (N) – Selects the first n elements from the collection
TakeWhile (Expression) – Keeps selecting elements from the collection while the expression is True. To select values while they’re smaller than 10, use the following lambda expression:
Function(n) n < 10
This expression selects values until it finds one that exceeds 10. The selection stops there, regardless of whether some of the following elements drop below 10.
Skip and SkipWhile The Skip and SkipWhile methods are equivalent to the Take and TakeWhile methods: They skip a number of items and select the remaining ones.
Distinct The Distinct method, finally, returns the distinct values in the collection:
Dim uniqueValues = data.Distinct