C#:如何使用 Enumerable.Aggregate 方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/970178/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C#: How to use the Enumerable.Aggregate method
提问by Svish
Lets say I have this amputated Person
class:
假设我有这个截肢Person
类:
class Person
{
public int Age { get; set; }
public string Country { get; set; }
public int SOReputation { get; set; }
public TimeSpan TimeSpentOnSO { get; set; }
...
}
I can then group on Age
and Country
like this:
然后我可以分组Age
并Country
喜欢这样:
var groups = aListOfPeople.GroupBy(x => new { x.Country, x.Age });
Then I can output all the groups with their reputation totals like this:
然后我可以像这样输出所有具有声誉总数的组:
foreach(var g in groups)
Console.WriteLine("{0}, {1}:{2}",
g.Key.Country,
g.Key.Age,
g.Sum(x => x.SOReputation));
My question is, how can I get a sum of the TimeSpentOnSO
property? The Sum
method won't work in this case since it is only for int
and such. I thought I could use the Aggregate
method, but just seriously can't figure out how to use it... I'm trying all kinds properties and types in various combinations but the compiler just won't recognize it.
我的问题是,我怎样才能得到TimeSpentOnSO
财产的总和?该Sum
方法在这种情况下不起作用,因为它仅适用于int
此类。我以为我可以使用该Aggregate
方法,但真的无法弄清楚如何使用它......我正在尝试各种组合的各种属性和类型,但编译器无法识别它。
foreach(var g in groups)
Console.WriteLine("{0}, {1}:{2}",
g.Key.Country,
g.Key.Age,
g.Aggregate( what goes here?? ));
Have I completely missunderstood the Aggregate method? Or what is going on? Is it some other method I should use instead? Or do I have to write my own Sum
variant for TimeSpan
s?
我完全误解了聚合方法吗?或者是怎么回事?这是我应该使用的其他方法吗?还是我必须Sum
为TimeSpan
s编写自己的变体?
And to add to the mess, what if Person is an anonymous class, a result from for example a Select
or a GroupJoin
statement?
更糟糕的是,如果 Person 是一个匿名类,例如来自 aSelect
或GroupJoin
语句的结果呢?
Just figured out that I could make the Aggregate
method work if I did a Select
on the TimeSpan
property first... but I find that kind of annoying... Still don't feel I understand this method at all...
刚刚发现Aggregate
如果我先Select
在TimeSpan
属性上做一个我可以使该方法起作用......但我觉得那种烦人......仍然觉得我根本不了解这种方法......
foreach(var g in groups)
Console.WriteLine("{0}, {1}:{2}",
g.Key.Country,
g.Key.Age,
g.Select(x => x.TimeSpentOnSO)
g.Aggregate((sum, x) => sum + y));
采纳答案by Svish
A combination of Chris and Daniels answers solved it for me. I needed to initialize the TimeSpan, and I did things in the wrong order. The solution is:
Chris 和 Daniels 的回答组合为我解决了这个问题。我需要初始化 TimeSpan,而且我以错误的顺序做事。解决办法是:
foreach(var g in groups)
Console.WriteLine("{0}, {1}:{2}",
g.Key.Country,
g.Key.Age,
g.Aggregate(TimeSpan.Zero, (sum, x) => sum + x.TimeSpentOnSO));
Thanks!
谢谢!
And also... D'oh!
还有……天啊!
回答by Marc Gravell
You could write TimeSpan
Sum
method...
你可以写TimeSpan
Sum
方法...
public static TimeSpan Sum(this IEnumerable<TimeSpan> times)
{
return TimeSpan.FromTicks(times.Sum(t => t.Ticks));
}
public static TimeSpan Sum<TSource>(this IEnumerable<TSource> source,
Func<TSource, TimeSpan> selector)
{
return TimeSpan.FromTicks(source.Sum(t => selector(t).Ticks));
}
Alternatively, MiscUtilhas generic-enabled Sum
methods, so Sum
should work on a TimeSpan
just fine (since there is a TimeSpan+TimeSpan=>TimeSpan
operator defined).
或者,MiscUtil具有启用泛型的Sum
方法,因此Sum
应该可以正常工作TimeSpan
(因为TimeSpan+TimeSpan=>TimeSpan
定义了运算符)。
Just pleasedon't tell me the number... it would scare me...
只是请不要告诉我号码......它会吓到我......
回答by Daniel Brückner
List<TimeSpan> list = new List<TimeSpan>
{
new TimeSpan(1),
new TimeSpan(2),
new TimeSpan(3)
};
TimeSpan total = list.Aggregate(TimeSpan.Zero, (sum, value) => sum.Add(value));
Debug.Assert(total.Ticks == 6);
回答by Chris Doggett
g.Aggregate(TimeSpan.Zero, (i, p) => i + p.TimeSpentOnSO)
Basically, the first argument to Aggregate is an initializer, which is used as the first value of "i" in the function passed in the second argument. It'll iterate over the list, and each time, "i" will contain the total so far.
基本上,Aggregate 的第一个参数是一个初始值设定项,它用作第二个参数中传递的函数中“i”的第一个值。它将遍历列表,每次,“i”将包含到目前为止的总数。
For example:
例如:
List<int> nums = new List<int>{1,2,3,4,5};
nums.Aggregate(0, (x,y) => x + y); // sums up the numbers, starting with 0 => 15
nums.Aggregate(0, (x,y) => x * y); // multiplies the numbers, starting with 0 => 0, because anything multiplied by 0 is 0
nums.Aggregate(1, (x,y) => x * y); // multiplies the numbers, starting with 1 => 120
回答by Joseph
You could sum on one of the Total properties of the TimeSpan. For instance, you could get the represented TotalHours of time spent on SO like this:
您可以对 TimeSpan 的 Total 属性之一求和。例如,您可以像这样获得花在 SO 上的表示的 TotalHours 时间:
g.Sum(x => x.SOReputation.TotalHours)
I believe this would give you the result you're looking for, but with the caveat that you'd have to put the units of measure according to what you need (hours, minutes, second, days, etc.)
我相信这会给你你正在寻找的结果,但需要注意的是,你必须根据你的需要(小时、分钟、秒、天等)来放置度量单位。