2009-06-09 5 views
19

私はこの切断されたPersonクラスを持っていると言うことができます:C#:Enumerable.Aggregateメソッドの使用方法

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メソッドを完全に誤解しましたか?または何が起こっている?代わりに使うべき他の方法ですか?あるいは、TimeSpanのために私自身のSumの変種を書かなければなりませんか?

さらに、Personが匿名クラスの場合、例えばSelectGroupJoinの文の結果はどうでしょうか?


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

あなたが必要とするもの(時間、分、秒、日など)に応じた単位の単位集計(削減)は、今私が遭遇した世界で最もクールなものの1つです私がそれを使いたいと思った状況。 :) –

答えて

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

ありがとう!

も... D'oh!

1

あなたは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)); 
} 

、を書くことができには汎用のSumメソッドがありますのでSumTimeSpanで動作するはずです(TimeSpan+TimeSpan=>TimeSpan演算子が定義されているため)。

だけは私に番号を教えていない...それは私を怖がらせるだろうしてください...

+0

ええ、それは私のバックアップパスの一種です。しかし、私はまだAggregateメソッドが実際にどのように機能するのかを知りたいです。それは私がそれを正常に使用することができないように私を悩ませるので:p – Svish

+0

そして、はい、その番号を永遠に秘密に保ちましょう。私の好奇心の種はそれを望んでいるとは言いますが、その場合はプライベートにしておきます。 – Svish

23
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); 
+0

TimeSpan.Zeroで初期化してください。非常に良い点。これにはTimeSpansのリストがありましたが、私はTimeSpanプロパティで他のもののリストが必要でした。しかし、私はそれを理解した。ありがとう! – Svish

14
g.Aggregate(TimeSpan.Zero, (i, p) => i + p.TimeSpentOnSO) 

基本的には、集計の最初の引数として使用されている初期化子であり、第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 
+0

これは私が既に解決していたintsであった。しかし、それを初期化する方法をクリアしていただきありがとうございます! – Svish

+0

元々はintsを使用していました。私は質問を誤解しましたが、これはあなたのために働くはずですし、Aggregateが一般的にどのように機能するかを説明する必要があります。 –

0

あなたがのTimeSpanの総特性の一つにまとめることができます。

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

私は、これはあなたが探している結果を与えるが、あなたは置く必要があるだろう警告してしまうと考えている:例えば、あなたはSOのように費やされた時間の表現TotalHoursを得ることができます

+0

実際これは私がやったことですが、他の理由からです。私はついにAggregateメソッド(専門家ではありませんが、p)を理解しています。 – Svish

関連する問題