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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 04:31:20  来源:igfitidea点击:

C#: How to use the Enumerable.Aggregate method

c#timeaggregate

提问by Svish

Lets say I have this amputated Personclass:

假设我有这个截肢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 Ageand Countrylike this:

然后我可以分组AgeCountry喜欢这样:

    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 TimeSpentOnSOproperty? The Summethod won't work in this case since it is only for intand such. I thought I could use the Aggregatemethod, 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 Sumvariant for TimeSpans?

我完全误解了聚合方法吗?或者是怎么回事?这是我应该使用的其他方法吗?还是我必须SumTimeSpans编写自己的变体?

And to add to the mess, what if Person is an anonymous class, a result from for example a Selector a GroupJoinstatement?

更糟糕的是,如果 Person 是一个匿名类,例如来自 aSelectGroupJoin语句的结果呢?



Just figured out that I could make the Aggregatemethod work if I did a Selecton the TimeSpanproperty first... but I find that kind of annoying... Still don't feel I understand this method at all...

刚刚发现Aggregate如果我先SelectTimeSpan属性上做一个我可以使该方法起作用......但我觉得那种烦人......仍然觉得我根本不了解这种方法......

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 TimeSpanSummethod...

你可以写TimeSpanSum方法...

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 Summethods, so Sumshould work on a TimeSpanjust fine (since there is a TimeSpan+TimeSpan=>TimeSpanoperator 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.)

我相信这会给你你正在寻找的结果,但需要注意的是,你必须根据你的需要(小时、分钟、秒、天等)来放置度量单位。