C#:如何使用Enumerable.Aggregate方法

Svi*_*ish 19 c# time aggregate

让我说我有这个截肢Person课:

class Person
{
    public int Age { get; set; }
    public string Country { get; set; }

    public int SOReputation { get; set; }
    public TimeSpan TimeSpentOnSO { get; set; }

    ...
}
Run Code Online (Sandbox Code Playgroud)

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

    var groups = aListOfPeople.GroupBy(x => new { x.Country, x.Age });
Run Code Online (Sandbox Code Playgroud)

然后我可以输出所有组的声誉总数如下:

foreach(var g in groups)
    Console.WriteLine("{0}, {1}:{2}", 
        g.Key.Country, 
        g.Key.Age, 
        g.Sum(x => x.SOReputation));
Run Code Online (Sandbox Code Playgroud)

我的问题是,我怎样才能得到一笔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??  ));
Run Code Online (Sandbox Code Playgroud)

我是否完全误解了Aggregate方法?或者发生了什么?是否应该使用其他方法?或者我是否必须SumTimeSpans 编写自己的变体?

如果添加到混乱中,如果Person是匿名类,例如a SelectGroupJoin语句的结果呢?


刚想通过我可以让这个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));
Run Code Online (Sandbox Code Playgroud)

Dan*_*ner 24

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);
Run Code Online (Sandbox Code Playgroud)


Chr*_*ett 14

g.Aggregate(TimeSpan.Zero, (i, p) => i + p.TimeSpentOnSO)
Run Code Online (Sandbox Code Playgroud)

基本上,Aggregate的第一个参数是初始化器,它在第二个参数中传递的函数中用作"i"的第一个值.它将遍历列表,每次"i"将包含到目前为止的总数.

例如:

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
Run Code Online (Sandbox Code Playgroud)


Svi*_*ish 2

克里斯和丹尼尔斯的答案组合为我解决了这个问题。我需要初始化 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));
Run Code Online (Sandbox Code Playgroud)

谢谢!

还有……噢!