19

この切断されたPersonクラスがあるとしましょう:

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

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

    ...
}

次に、次のようにグループ化できますAgeCountry

    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??  ));

Aggregate メソッドを完全に誤解していますか? または何が起こっているのですか?代わりに使用する必要がある他の方法はありますか?または、s の独自のSumバリアントを作成する必要がありTimeSpanますか?

混乱に加えて、 Person が匿名クラスで、たとえば aSelectまたはGroupJoinステートメントの結果である場合はどうなるでしょうか?


最初にプロパティを実行すると、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));
4

5 に答える 5

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);
于 2009-06-09T13:53:06.767 に答える
14
g.Aggregate(TimeSpan.Zero, (i, p) => i + p.TimeSpentOnSO)

基本的に、Aggregate の最初の引数は初期化子であり、2 番目の引数で渡される関数の "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
于 2009-06-09T13:54:26.610 に答える
2

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));

ありがとう!

そしてまた...おお!

于 2009-06-09T14:02:23.113 に答える
1

メソッドを書くことができます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));
}

あるいは、MiscUtilにはジェネリック対応のSumメソッドがあるため、問題なく動作するSumはずTimeSpanです (TimeSpan+TimeSpan=>TimeSpan演算子が定義されているため)。

ただ番号は教えないでください...怖いです...

于 2009-06-09T13:51:36.817 に答える
0

TimeSpan の Total プロパティの 1 つを合計できます。たとえば、SO に費やされた合計時間は次のように取得できます。

g.Sum(x => x.SOReputation.TotalHours)

これで探している結果が得られると思いますが、必要に応じて測定単位を入力する必要があることに注意してください(時間、分、秒、日など)。

于 2009-06-09T14:23:34.287 に答える