c# Linq Aggregate()累加函数的用法

15 篇文章 0 订阅

Enumerable.Aggregate 扩展方法在System.Linq命名空间中,是Enumerable类的第一个方法(按字母顺序排名),但确是Enumerable里面相对复杂的方法。
MSDN对它的说明是:对序列应用累加器函数。备注中还有一些说明,大意是这个方法比较复杂,一般情况下用Sum、Max、Min、Average就可以了。
看看下面的代码,有了Sum,谁还会用Aggregate呢!

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);
}
Aggregate是对序列应用累加器的函数。

同是求和,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做不到吧!

同理 例如我们这样的一个list集合,我们想要得到
List<string> lst = new List<string>() { "张三", "李四", "王麻子" };
"张三 哈哈哈 李四 哈哈哈 王麻子 "
这样的一个结果;
假如我们没有linq,我们该怎么去写这个代码呢?
可能和下面这段代码没有多少出入!

string str = "";
 
for (int i = 0; i < lst.Count; i++)
{
  str += lst[i] + " 哈哈哈 ";
}
Console.WriteLine(str);

那如果使用linq的扩展方法Aggregate就显得简单的多了

str = lst.Aggregate((first, second) => $"{first} 哈哈哈 {second} ");

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
倒置:able was I ere I saw Alba

怎么中间的都一样,两的单词首尾字母大小写发生转换了呢?!
仔细看看吧,不是算法有问题,是输入“有问题”。搜索一下“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扩展

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);
}

再举例加深理解

int[] myIntArray = { 1, 2, 3, 4, 5 };
Console.WriteLine(myIntArray.Aggregate((paramA, paramB) => paramA * 2 + paramB));
//结果为57

过程如下:

(((1*2+2)*2+3)*2+4)*2+5=57

所以可以得出结论,Aggregate累加器接收到的第一个元素作为paramA,以后接收的元素都存在paramB与paramA进行运算,并且运算结果存在paramA中后与新的paramB进行下一轮计算

文章截取自:

https://blog.csdn.net/qq_39377889/article/details/115102806
http://t.zoukankan.com/ywsoftware-p-3128764.html
https://blog.csdn.net/qq_43206083/article/details/124716831?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165578021316780366553107%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=165578021316780366553107&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2blogfirst_rank_ecpm_v1~rank_v31_ecpm-1-124716831-null-null.nonecase&utm_term=aggregate&spm=1018.2226.3001.4450

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值