在Linq中有一些這樣的操作,根據集合計算某一單一值,比如集合的最大值,最小值,平均值等等。Linq中包含7種操作,這7種操作被稱作聚合操作。
1、Count操作,計算序列中元素的個數,或者計算滿足一定條件的元素的個數
2、Sum操作,計算序列中所有元素的值的總和
3、Max操作,計算序列中元素的最大值
4、Min操作,計算序列中元素的最小值
5、Average操作,計算序列中所有元素的平均值
6、Aggregate操作,對集合中的元素進行自定義的聚合計算
7、LongCount操作,計算集合中的元素的數量,或者滿足一定條件的元素的數量,一般用來計算大型集合中元素的數量
下面我們就來對這些聚合操作來做逐一的分析。
Count操作
Count操作是用來計算序列中元素的數量或者滿足一定條件的元素的數量。Count()方法的原型:
public static int Count<TSource>(this IEnumerable<TSource> source); public static int Count<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
Count方法有2個原型,第一個只是單獨的計算序列中的元素的數量總和,第二個原型有一個委托函數,用來篩選滿足一定條件的元素,然后再計算滿足條件的數量和。下面我們舉個例子來說明:
1 private void CountQuery() 2 { 3 int[] ints = new int[] { 1,2,3,4,5,6,7 }; 4 5 6 var result = ints.Count(); 7 var result2 = ints.Count(x => x > 4); 8 9 Response.Write(result + "</br>"); 10 11 Response.Write(result2 + "</br>"); 12 13 }
這個例子中result是計算ints數組的總數量,result計算的是ints中元素值大於4的元素個數。
看看運行結果:
這種求和過程也很簡單
Sum操作
Sum操作計算序列中所有元素的和。Sum函數的原型比較多,這里不一一列舉。看例子:
1 private void SumQuery() 2 { 3 int[] ints = new int[] { 1,2,3,4,5,6,7 }; 4 5 6 var result = ints.Sum(); 7 8 9 Response.Write(result + "</br>"); 10 11 12 13 }
看看結果:
Max操作
Max操作來計算序列中元素的最大值。
1 private void MaxQuery() 2 { 3 int[] ints = new int[] { 1,2,3,4,5,6,7 }; 4 5 6 var result = ints.Max(); 7 8 9 Response.Write(result + "</br>"); 10 11 12 13 }
Min操作
Min操作來計算序列中元素的最小值。
1 private void MinQuery() 2 { 3 int[] ints = new int[] { 1,2,3,4,5,6,7 }; 4 5 6 var result = ints.Min(); 7 8 9 Response.Write(result + "</br>"); 10 11 12 13 }
Average操作
Average操作是計算序列的所有元素的平均值。
1 private void AverageQuery() 2 { 3 int[] ints = new int[] { 1,2,3,4,5,6,7 }; 4 5 6 var result = ints.Average(); 7 8 9 Response.Write(result + "</br>"); 10 11 12 13 }
Aggregate操作
Aggregate操作,上面的一些都比較簡單,我們重點來分析一下Aggregate操作。Aggregate操作能夠對集合中的元素進行自定義的聚合計算。Aggregate()函數有3種原型:
public static TSource Aggregate<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func); public static TAccumulate Aggregate<TSource, TAccumulate>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func); public static TResult Aggregate<TSource, TAccumulate, TResult>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func, Func<TAccumulate, TResult> resultSelector);
其中source表示數據源,func表示累加器函數,seed表示累加器的初始值,resultSelector表示轉換結果函數。
下面我們用一個詳細的例子來分累加是如何操作的。
首先我們創建一個整型數組ints,值是0~99.
使用Aggregate計算ints中的素有元素之和。
1 private void AggregateQuery() 2 { 3 int[] ints = new int[100]; 4 5 for (int i = 0; i < 100; i++) 6 { 7 ints[i]=i; 8 } 9 10 var result = ints.Aggregate((a,b) => a+b); 11 12 13 Response.Write(result + "</br>"); 14 15 16 17 }
計算結果:
我們看第一個原型的累加過程:
最終就是通過遍歷數據源的每一個元素,根據我們傳如的累加函數來累加。比如我們累加函數是求所有元素的和,那么累加函數就是func(a,b){a+b},如果求所有元素的乘積,那么累加函數就是func(a,b){a*b}.
參數a,b的意義:a表示當前元素之前的所有數據根據累加函數求得的值,b就是當前元素。
我們看第二個累加原型:
第二個累加原型有一個累加基數seed,就表示在這個seed基礎上進行累加。比如上面我們創建的數組是0~99,累加和是4950.那么我給累加seed這個基數設置為100,那么累加和就是4950+100=5050.
1 private void AggregateQuery() 2 { 3 int[] ints = new int[100]; 4 5 for (int i = 0; i < 100; i++) 6 { 7 ints[i]=i; 8 } 9 10 var result = ints.Aggregate(100,(a,b) => a+b); 11 12 13 Response.Write(result + "</br>"); 14 15 16 17 }
看看結果:
看源碼分析也確實是這樣子的:
第三個原型又多了一個委托函數,這個委托函數是對累加的結果做進一步處理然后返回處理后的結果。我們先看看源碼分析:
從累加原型的源碼看出,把最終的累加結果又傳給resultSelector方法進行進一步處理。
我們看個簡單的例子:
1 private void AggregateQuery() 2 { 3 int[] ints = new int[100]; 4 5 for (int i = 0; i < 100; i++) 6 { 7 ints[i]=i; 8 } 9 10 var result = ints.Aggregate(100,(a,b) => a+b,x=>x*-1); 11 12 13 Response.Write(result + "</br>"); 14 15 16 17 }
從代碼可以看出,我們最終累加的值,然后對它乘以-1返回結果。我們預測應該返回-5050.
看看結果:
看來我們經過源碼分析,最終得到了驗證,我們的分析是正確的。
LongCount操作
LongCount和Count一樣,都是計算序列中元素的數量或者滿足一定條件的元素的數量,一般longcount用來計算大型的集合。但是從源代碼中我沒看到LongCount和Count的計算方法有什么不同,只是計算和的num的聲明不同,Count的num聲明為int類型,而LongCount的num聲明為long類型,數據范圍擴大了而已,這里就不再重復講解了,參考Count即可。