Aggregate

LINQ provides several aggregation extension methods: Aggregate, Average, Count, LongCount, Max, Min and Sum. The aggregation methods all take a list of objects and reduces that list to a single result. Conceptually it helps to think of Aggregate as a generic building block and the others aggregation methods (Average, Max, etc.) as special cases of Aggregate. In functional programming languages, such as F#, Aggregate is usually named fold (or inject in Ruby). The SQL like name Aggregate leads developers to write off Aggregate as purely for numeric aggregation purposes. In fact, Aggregate can be used whenever we want to build a single object from a group of objects.

So how does Aggregate work?

Looking at the Aggregate method signature is a pretty scary experience:

public static TAccumulate Aggregate<TSource, TAccumulate>(
	this IEnumerable<TSource> source,
	TAccumulate seed,
	Func<TAccumulate, TSource, TAccumulate> func
)

The Aggregate methods takes a list of source objects, a seed value and an accumulator function which it processes as follows:

  • The accumulator function is called for each item in the list and returns a value
  • The first time the accumulator function is called the seed and the first item in the list are passed to it
  • The accumulator function is called again with the result of the first accumulator function call and the second item in the list as its parameters
  • This continues until all items in the list are processed
  • The result of the last call to the accumulator function is returned as the result of the entire Aggregate method

This can take some getting your head around. Here is an example:

var whiskeyNames = new [] {"Ardbeg 1998", "Glenmorangie","Talisker", "Cragganmore"};

var listOfWhiskies = whiskeyNames.Aggregate("Whiskies: ", (accumulated, next) =>
{
	Console.Out.WriteLine("(Adding [{0}] to the list [{1}])", next, accumulated);
	return accumulated + " " + next;
});

Console.Out.WriteLine(listOfWhiskies);

This outputs:

(Adding [Ardbeg 1998] to the list [Whiskies: ])
(Adding [Glenmorangie] to the list [Whiskies:  Ardbeg 1998])
(Adding [Talisker] to the list [Whiskies:  Ardbeg 1998 Glenmorangie])
(Adding [Cragganmore] to the list [Whiskies:  Ardbeg 1998 Glenmorangie Talisker])
Whiskies:  Ardbeg 1998 Glenmorangie Talisker Cragganmore

The seed parameter is optional. If it is omitted the first two items in the list will be passed to the function, as this example demonstrates:

listOfWhiskies = whiskeyNames.Aggregate((accumulated, next) =>
{
	Console.Out.WriteLine("(Adding [{0}] to the list [{1}])", next, accumulated);
	return accumulated + " " + next;
});

Console.Out.WriteLine(listOfWhiskies);

This outputs:

(Adding [Glenmorangie] to the list [Ardbeg 1998])
(Adding [Talisker] to the list [Ardbeg 1998 Glenmorangie])
(Adding [Cragganmore] to the list [Ardbeg 1998 Glenmorangie Talisker])
Ardbeg 1998 Glenmorangie Talisker Cragganmore

Finding the best item in a list

Whiskey mostExpensiveWhiskey = whiskies.Aggregate((champion, challenger) => challenger.Price > champion.Price ? challenger : champion);
Console.WriteLine("Most expensive is {0}", mostExpensiveWhiskey.Name);

Creating a new ‘aggregated’ object

var blendedWhiskey = whiskies.Where(x=> x.Country == "Scotland")
.Aggregate(new Whiskey() { Name="Tesco value whiskey", Age=3, Country="Scotland" },
	(newWhiskey, nextWhiskey) =>
	{
		newWhiskey.Ingredients.Add(nextWhiskey);
		newWhiskey.Price += (nextWhiskey.Price / 10);
		return newWhiskey;
	});

Alternative to Cunt

// 0 is the seed, and for each item, we effectively increment the current value.
// In this case we can ignore "item" itself.
int count = sequence.Aggregate(0, (current, item) => current + 1);

Summing numbers

var nums = new[]{1,2,3,4};
var sum = nums.Aggregate( (a,b) => a + b);
Console.WriteLine(sum); // output: 10 (1+2+3+4)

Note:

the aggregate result type an seed type is the same. You can use lambda expresion or lambda statement(need return) as accumulate function.

Reference:

1. Refactoring to LINQ Part 2: Aggregate is Great

2. LINQ Aggregate algorithm explained

时间: 2024-10-24 21:44:06

Aggregate的相关文章

mongodb aggregate and mapReduce

Aggregate MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果.有点类似sql语句中的 count(*) 语法如下: db.collection.aggregate() db.collection.aggregate(pipeline,options) db.runCommand({ aggregate: "<collection>", pipeline: [ <stage>, <...&g

cacti系列之图形合并插件aggregate(二)

资源的需求是随着业务的发展逐步增加的,而在网络规范之初,为了节省资金,我们只会在IDC申请少量的机柜:随着业务扩张,需求增加,老区域可能没有空闲的机柜资源了,只能在机房临近的区域申请机柜,这样就会存在多个外网上行端口.为了方便流量的直观监控,我们就需要把多个外网上行口流量进行合并. 今天我们就来看看怎样实现流量合并. 一.下载并安裝aggregate插件: # 下载aggregate插件并解压至cacit安装目录下的plugins目录. [[email protected]_6.213 ~] w

MongoDB University 第五周作业——aggregate聚合高级查询

HOMEWORK: HOMEWORK 5.2 (HANDS ON) Crunching the Zipcode datasetPlease calculate the average population of cities in California (abbreviation CA) and New York (NY) (taken together) with populations over 25,000. For this problem, assume that a city nam

使用aggregate在MongoDB中查找重复的数据记录

我们知道,MongoDB属于文档型数据库,其存储的文档类型都是JSON对象.正是由于这一特性,我们在Node.js中会经常使用MongoDB进行数据的存取.但由于Node.js是异步执行的,这就导致我们无法保证每一次的数据库save操作都是原子型的.也就是说,如果客户端连续两次发起同一事件将数据存入数据库,很可能会导致数据被重复保存.高并发的情况下,哪怕是你在代码中已经做了非常严格的校验,例如插入数据前判断要保存的数据是否已经存在,但仍然有可能会出现数据被重复保存的风险.因为在异步执行中,你没有

04 LINQ中的聚合函数(Aggregate function in LINQ)

试想一下,我们有一个List<int>数组,现在我们想对List中的所有值求和.在没学习LINQ之前我们会轻松的写出下面的代码: static void Main(string[] args) { List<int> array = new List<int>() { 1, 3, 3, 2, 7, 3, 2, 8, 5, 4, 6 }; int sum = 0; foreach (int item in array) { sum += item; } Console.W

MongoDB聚合运算之group和aggregate聚集框架简单聚合(10)

聚合运算之group 语法: db.collection.group( { key:{key1:1,key2:1}, cond:{}, reduce: function(curr,result) { }, initial:{}, finalize:function() { } } ) key: 分组字段 cond:查询条件 reduce:聚合函数 initial:初始化 finalize:统计一组后的回调函数 #查询每个栏目下的商品数量 db.goods.group( { key:{cat_id

MongoDB Aggregate

1. sum { "_id" : ObjectId("50b1aa983b3d0043b51b2c52"), "name" : "Nexus 7", "category" : "Tablets", "manufacturer" : "Google", "price" : 199 } select manufacturer,cou

The Aggregate Magic Algorithms

http://aggregate.org/MAGIC/ The Aggregate Magic Algorithms There are lots of people and places that create and collect algorithms of all types (here are a few WWW sites). Unfortunately, in building systems hardware and software, we in The Aggregate o

细说Linq之Aggregate

前言 Linq中有关常见的方法我们已经玩的得心应手,而对于那些少用的却是置若罔闻(夸张了点),但只有在实际应用中绞尽脑汁想出的方法还不如内置的Linq方法来的实际和简洁 之前在Ruby中演示了一段代码来讲述Ruby的神奇,下面我们再来看一下: sum = 0 i = 0 (1..101).each do|elem|   sum+=i   i+=1end puts sum 是的就是这段代码,求1到100的和,代码的优美和简洁让我惊叹. 通过C#继续引入话题 如果你是有两年工作经验以上的人,当在面试