在Linq中有一些这样的操做,根据集合计算某一单一值,好比集合的最大值,最小值,平均值等等。Linq中包含7种操做,这7种操做被称做聚合操做。数组
一、Count操做,计算序列中元素的个数,或者计算知足必定条件的元素的个数函数
二、Sum操做,计算序列中全部元素的值的总和源码分析
三、Max操做,计算序列中元素的最大值this
四、Min操做,计算序列中元素的最小值spa
五、Average操做,计算序列中全部元素的平均值code
六、Aggregate操做,对集合中的元素进行自定义的聚合计算blog
七、LongCount操做,计算集合中的元素的数量,或者知足必定条件的元素的数量,通常用来计算大型集合中元素的数量原型
下面咱们就来对这些聚合操做来作逐一的分析。源码
Count操做it
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便可。