C#:如何使用 Enumerable.Aggregate 方法
假设我有这个被截断的 Person
类:
class Person
{
public int Age { get; set; }
public string Country { get; set; }
public int SOReputation { get; set; }
public TimeSpan TimeSpentOnSO { get; set; }
...
}
然后我可以像这样对 Age
和 Country
进行分组:
var groups = aListOfPeople.GroupBy(x => new { x.Country, x.Age });
然后我可以输出所有组及其声誉总计如下:
foreach(var g in groups)
Console.WriteLine("{0}, {1}:{2}",
g.Key.Country,
g.Key.Age,
g.Sum(x => x.SOReputation));
我的问题是,如何获得 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?? ));
我是否完全误解了聚合方法? 或者发生了什么事? 我应该使用其他方法吗? 或者我是否必须为 TimeSpan
编写自己的 Sum
变体?
更糟糕的是,如果 Person 是一个匿名类,例如来自 Select
或 GroupJoin
语句的结果,该怎么办?
只是发现如果我先对 TimeSpan
属性执行 Select
,我就可以使 Aggregate
方法起作用......但我发现这种情况烦人的...仍然觉得我根本不理解这个方法...
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));
Lets say I have this amputated Person
class:
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:
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.
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?
And to add to the mess, what if Person is an anonymous class, a result from for example a Select
or a GroupJoin
statement?
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...
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));
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
基本上,Aggregate 的第一个参数是一个初始值设定项,它用作第二个参数中传递的函数中“i”的第一个值。 它将迭代列表,每次“i”将包含到目前为止的总数。
例如:
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.
For example:
您可以编写
TimeSpan
Sum
方法...或者,MiscUtil 具有启用泛型的
Sum
方法,因此Sum
应该可以在TimeSpan
上正常工作(因为有定义的TimeSpan+TimeSpan=>TimeSpan
运算符)。只是请不要告诉我号码...这会吓到我...
You could write
TimeSpan
Sum
method...Alternatively, MiscUtil has generic-enabled
Sum
methods, soSum
should work on aTimeSpan
just fine (since there is aTimeSpan+TimeSpan=>TimeSpan
operator defined).Just please don't tell me the number... it would scare me...
克里斯和丹尼尔斯的答案组合为我解决了这个问题。 我需要初始化 TimeSpan,但我按错误的顺序执行操作。 解决办法是:
谢谢!
还有... 天啊!
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:
Thanks!
And also... D'oh!
您可以对 TimeSpan 的 Total 属性之一求和。 例如,您可以像这样获得在 SO 上花费的时间的代表 TotalHours:
我相信这会给您带来您正在寻找的结果,但需要注意的是您必须根据您的情况设置度量单位需要(小时、分钟、秒、天等)
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:
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.)