Enumerable.Aggregate 扩展方法在System.Linq命名空间中,是Enumerable类的第一个方法(按字母顺序排名),但确是Enumerable里面相对复杂的方法。

MSDN对它的说明是:对序列应用累加器函数。备注中还有一些说明,大意是这个方法比较复杂,一般情况下用Sum、Max、Min、Average就可以了。
看看下面的代码,有了Sum,谁还会用Aggregate呢!

也很简单吧,就是一个循环!前面lambda表达式中参数a, n 分别对应current, enumerator.Current,对照一下,还是很好理解的。

现在我们想求整数数组中位置为偶数的数的和(间隔求和),可以用Where配合Sum:

public static void Test5()
        {
            int[] nums = new int[] { 10, 20, 30, 40, 50 };
            int sum1 = nums.Where((n, i) => i % 2 == 0).Sum();//10 + 30 + 50
        }

这个Where扩展设计的很好,它不但能带出某项的值“n”,还能带出项的位置“i”。
Aggregate可不行!我们来改进一下:

//改进的Aggerate扩展(示例代码,实际使用请添加空值检查)
public static TSource Aggregate<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, int, TSource> func)
{
  int index = 0;
  using (IEnumerator<TSource> enumerator = source.GetEnumerator())
  {
    enumerator.MoveNext();
    index++;
    TSource current = enumerator.Current;
    while (enumerator.MoveNext())
    current = func(current, enumerator.Current, index++);
    return current;
  }
}

改进后的Aggregate更加强大,前面的求偶数位置数和的算法可以写成下面的样子:

public static void Test6()
        {
            int[] nums = new int[] { 10, 20, 30, 40, 50 };
            int sum2 = nums.Aggregate((a, c, i) => a + i%2 == 0 ? c : 0 );//10 + 30 + 50
        }

可能不够简洁,但它一个函数代替了Where和Sum。所在位置“i“的引入给Aggregate带来了很多新的活力,也增加了它的应用范围!

使用“初中知识”实现查找重复最优算法 + 最终极限算法》中最后提出的“最终极限算法”,用上这里改进的Aggregate扩展,也可以甩开Select和Sum,更加精简一步了:

        public static void Test7()
        {
            //1~n放在含有n+1个元素的数组中,只有唯一的一个元素值重复,最简算法找出重复的数
            int[] array = new int[] { 1, 3, 2, 3, 4, 5 };
            //原极限算法
            int repeatedNum1 = array.Select((i, j) => i - j).Sum();
            //最新极限算法
            int repeatedNum2 = array.Aggregate((a, n, i) => a + n - i);
        }
        public static void Test1()
        {
            int[] nums = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};             int sum1 = nums.Sum();
            int sum2 = nums.Aggregate((i,j)=>i+j);
        }

同是求和,Sum不再需要额外参数,而Aggregate确还要将一个lambda作为参数。因为用起来麻烦,操作太低级,Aggregate渐渐被大多人忽视了...
实际上Aggregate因为“低级”,功能确是很强大的,通过它可以简化很多聚合运算。

首先来看对Aggregate组装字符串的问题:

        public static void Test2()
        {
            string[] words = new string[] { "Able", "was", "I", "ere", "I", "saw", "Elba"};
            string s = words.Aggregate((a, n) => a + " " + n);
            Console.WriteLine(s);
        }

输出结果是:Able was I ere I saw Elba (注:出自《大国崛起》,狄娜最后讲述了拿破仑一句经典)。
当然考虑性能的话还是用StringBuilder吧,这里主要介绍用法。这个Sum做不到吧!

Aggregate还可以将所有字符串倒序累加,配合String.Reverse扩展可以实现整个句子的倒序输出:

        public static void Test3()
        {
            string[] words = new string[] { "Able", "was", "I", "ere", "I", "saw", "Elba"};
            string normal = words.Aggregate((a, n) => a + " " + n);
            string reverse = words.Aggregate((a, n) => n.Reverse() + " " + a);             Console.WriteLine("正常:" + normal);
            Console.WriteLine("倒置:" + reverse);
        }
        // 倒置字符串,输入"abcd123",返回"321dcba"
        public static string Reverse(this string value)
        {
            char[] input = value.ToCharArray();
            char[] output = new char[value.Length];
            for (int i = 0; i < input.Length; i++)
                output[input.Length - 1 - i] = input[i];
            return new string(output);
        }

看下面,输出结果好像不太对:

怎么中间的都一样,两的单词首尾字母大小写发生转换了呢?!
仔细看看吧,不是算法有问题,是输入“有问题”。搜索一下“Able was I ere I saw Elba”,这可是很有名的英文句子噢!

Aggregate还可以实现异或(^)操作

        public static void Test4()
        {
            byte[] data = new byte[] { 0x31, 0x32, 0x33, 0x34, 0x35 };
            byte checkSum = data.Aggregate((a, n) => (byte)(a ^ n));
        }

对经常作串口通信的朋友比较实用。

看来Aggregate也是比较“简单易用”的,深入一步来看看它是怎么实现的吧,使用Reflector,反编译一下System.Core.dll。
以下代码取自反编译结果,为了演示删除了其中的空值判断代码:

 public static TSource Aggregate<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func)
        {
            using (IEnumerator<TSource> enumerator = source.GetEnumerator())
            {
                enumerator.MoveNext();
                TSource current = enumerator.Current;
                while (enumerator.MoveNext())
                    current = func(current, enumerator.Current);
                return current;
            }
        }
 

C#累加器函数Aggregate用法 讲解的更多相关文章

  1. tf.transpose函数的用法讲解

    tf.transpose函数中文意思是转置,对于低维度的转置问题,很简单,不想讨论,直接转置就好(大家看下面文档,一看就懂). tf.transpose(a, perm=None, name='tra ...

  2. python中map()函数的用法讲解

    map函数的原型是map(function, iterable, -),它的返回结果是一个列表. 参数function传的是一个函数名,可以是python内置的,也可以是自定义的. 参数iterabl ...

  3. MySQL中 IFNULL、NULLIF和ISNULL函数的用法

    mysql 中 ifnull().nullif().isnull()函数的用法讲解: 一.IFNULL(expr1,expr2)用法: 假如expr1不为NULL,则 IFNULL() 的返回值为ex ...

  4. Linq扩展方法之Aggregate 对序列应用累加器函数

    Linq扩展方法之Aggregate  对序列应用累加器函数; 函数模板:// 函数名:对序列应用累加器函数. // Parameters:参数要求 // source:要聚合的 System.Col ...

  5. LINQ中的Aggregate用法总结

    Aggregate这个语法可以做一些复杂的聚合运算,例如累计求和,累计求乘积.它接受2个参数,一般第一个参数是称为累积数(默认情况下等于第一个值),而第二个代表了下一个值.第一次计算之后,计算的结果会 ...

  6. python中open函数的用法

    用法如下: name = open('errname.txt','w')name.readline()name.close() 1.看下第一行的代码 用来访问磁盘中存放的文件,可以进行读写等操作,例如 ...

  7. 详解php 获取文件名basename()函数的用法

    PHP 中basename()函数给出一个包含有指向一个文件的全路径的字符串,此函数返回基本的文件名,本篇文章收集了关于使用PHP basename()函数获取文件名的几篇文章,希望对大家理解使用PH ...

  8. PHP截取字符串函数substr()函数实例用法详解

    在PHP中有一项非常重要的技术,就是截取指定字符串中指定长度的字符.PHP对于字符串截取可以使用PHP预定义函数substr()函数来实现.下面就来介绍一下substr()函数的语法及其应用. sub ...

  9. 有关日期的函数操作用法总结,to_date(),trunc(),add_months();

    相关知识链接: Oracle trunc()函数的用法 oracle add_months函数 Oracle日期格式转换,tochar(),todate() №2:取得当前日期是一个星期中的第几天,注 ...

随机推荐

  1. python下爬某个网页的图片

    #coding=utf-8 import re import urllib def getHtml(url): #获取url对应得源码 page = urllib.urlopen(url) html ...

  2. ES(6): access elasticsearch via curl

    curl是一个非常实用的.用来与服务器之间传输数据的工具:支持的协议包括 (DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS, IMAP, IMAPS, LDAP, ...

  3. The superclass "javax.servlet.http.HttpServlet" was not found

    在eclipse中,需要通过

  4. 用7z.exe 压缩整个文件夹里的内容

    以下是批处理中的内容: 7z.exe a -tzip zmv9netSrc.zip "D:\IE收藏夹备份\*"pause7z.exe a -tzip zmv9netSrc.zip ...

  5. 如何在UltraEdit中高亮显示PB代码

    打开UE,从菜单中选择高级->配置… 点击打开按钮,注意文件WordFile.txt最后一个高亮显示语言的编号,格式为“ /L(number) ”,假设最后一个高亮显示语言的编号是15,修改UE ...

  6. Maven基本使用

    Maven基本使用 一.安装 先去官网下载maven(http://maven.apache.org/download.cgi) 下载下来解压后如下所示  配置环境变量   查看配置成功与否  mav ...

  7. Java技术专题之JVM你的内存泄露了吗?

    一.从一个例子开始 关于JVM的内存泄露,让我们从下面一个例子开始吧,大家来判断一下如果按照下面这种分配方式,会不会出现内存泄露呢? import java.util.List; import jav ...

  8. C++ static类成员,static类成员函数

    转载:ZJE_ANDY static修饰类中成员,表示类的共享数据 1.static类成员 C++primer里面说过,static类成员不像普通的类数据成员,static类数据成员独立于一切类对象处 ...

  9. Zabbix监控windows的CPU利用率和其他资源

    zabbix的WEB端--配置-模板--Template OS Windows--项目--创建项目 名称:UserPerfCountercpu 键值:UserPerfCountercpu 数据类型:数 ...

  10. TMOD

    1. • tag/itemlist {{Syntax Error}} Debug info: Unexpected token else Waiting... Debug info: node D:/ ...