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. 重置SQL Server sa密码

    查询分析器,连接时,身份验证使用"使用windows身份验证" 然后,执行: EXEC sp_password NULL, '新密码', 'Sa'

  2. android自定义tabhost,tabcontent用intent获得

    地址:http://my.oschina.net/aowu/blog/36282 自己改的自定义tabhost组建,效果图如左.有更好的朋友可以相互交流一下,嘿嘿. 1.先上AndroidManife ...

  3. theme为dialog的Activity如何充满全屏

     转自:http://blog.csdn.net/fzh0803/article/details/9787615 分类: android_点滴记录2013-08-06 10:33 2005人阅读 评论 ...

  4. 【Spring学习笔记-MVC-16】Spring MVC之重定向-解决中文乱码

    概述 spring MVC框架controller间跳转,需重定向,主要有如下三种: 不带参数跳转:形如:http://localhost:8080/SpringMVCTest/test/myRedi ...

  5. QSqlDatabase: QMYSQL driver not loaded

    转载:KiteRunner24 在Qt 5.9中使用数据库连接时,弹出下面的错误: QSqlDatabase: QMYSQL driver not loaded QSqlDatabase: avail ...

  6. bzoj 1414: [ZJOI2009]对称的正方形

    Description Orez很喜欢搜集一些神秘的数据,并经常把它们排成一个矩阵进行研究.最近,Orez又得到了一些数据,并已经把它们排成了一个n行m列的矩阵.通过观察,Orez发现这些数据蕴涵了一 ...

  7. centos1.7 配置nginx+php+mysql客户端+thinkphp的rewrite实现

    1   . 安装php7     下载地址:https://secure.php.net/downloads.php这里下载的是:wget http://ar2.php.net/distributio ...

  8. 1035 Password (20 分)

    1035 Password (20 分) To prepare for PAT, the judge sometimes has to generate random passwords for th ...

  9. 邮件服务器fixpost服务(1)

    发邮件所用的协议,SMTP协议,端口TCP25 收邮件所用的协议,pop3.imap协议 邮件客户端(MUA):foxmail.闪电邮.邮件大师.outlook 搭建邮件服务器所用到的软件(MTA邮件 ...

  10. [UE4]使机器人受伤