Web常用工具 二维码美化 在线压缩 JavaScript AI工具汇总网站 ASP.NET控件源码查询 W3CHTML W3SCHOOL 开源中国 51aspx github codeproject SQLBACKUP 几种排序算法比较 SQL中deny权限 MSDN下载 HttpWebRequest类 HTML5 stackoverflow ASP.NET 页生命周期概述 IIS 5.0 和 6.0 的 ASP.NET 应用程序生命周期概述 [SQL Server]视图sys.sysprocesses brnshop学习 SQL视频 Fiddler帮助文档 Sprint.Net SQLServer牛人博客 codeplex IIS官网 IE11 Developer Jquery源码视频上 Jquery源码视频下 Jquery Bugs jquery.miaov.com 正则表达式 Jquery API 1.9 Service Broker Javascript Object中的方法讲解 Microsoft webcast 微信开发接口 ECMAScript5 Underscore Jquery Bugs SQL存储过程事务嵌套 官网SQL事务锁 2345天气插件 Json数据查看 C++ jquery-plugin-validate 博学谷(传智播客) Swift视频 IOS代码论坛 SWIFT设计模式 操作系统下载 AngularJS VueJS ASPNETCORE 前端题库 Node.js ASPNETCORE 腾讯课堂 SwiftUI SwiftUI疑问解答 ADO.NET SMO 数字化企业网 Unicode码查询 Redis使用文档 .NET 微服务:适用于容器化 .NET 应用程序的体系结构 .NETCore5.0微软官方文档 CSS3.0 在 ASP.NET Core 中配置 Windows 身份验证 Maven使用教程 Maven Repository Thymeleaf Thymeleaf中文CSDN Spring官方文档 Spring中文文档 SpringBoot SpringData SVG在线设计工具 SVG教程01 SVG教程02 fontawesome图标库 mybatis官网 mybatis-spring中文 mysql教程 python教程 python的scrapy教程01 python的scrapy教程02 VS开发python xpath教程 腾讯向量数据库教程 JSZip浏览器内存中创建文件与文件夹 axios的使用文档 SheetJS(JS操作excel)的使用文档

huaan011

 

C#累加器函数Aggregate用法 讲解

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[] { 1020304050 };
            
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[] { 1020304050 };
            
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[] { 132345 };
            
//原极限算法
            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[] { 12345678910};

            
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[] { 0x310x320x330x340x35 };
            
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;
            }
        }

 

posted on 2014-04-02 22:45  华安  阅读(9595)  评论(0编辑  收藏  举报

导航