この切断された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?? ));
Aggregateメソッドを完全に誤解しましたか?または何が起こっているのですか?代わりに使用する必要がある他の方法はありますか?または、Sum
s用に独自のTimeSpan
バリアントを作成する必要がありますか?
そして、混乱に加えて、Personが匿名クラスである場合、たとえばSelect
またはGroupJoin
ステートメントの結果はどうなりますか?
最初にAggregate
プロパティでSelect
を実行すると、TimeSpan
メソッドを機能させることができることがわかりました...しかし、そのような迷惑なことに気づきました...それでも私はこの方法をまったく理解していないと感じています...
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));
クリスとダニエルズの答えの組み合わせは私のためにそれを解決しました。 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!
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);
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
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
演算子定義)。
ただお願いします番号を教えてはいけません...それは私を怖がらせるでしょう...
TimeSpanのTotalプロパティの1つを合計することができます。たとえば、次のようにSOに費やされた合計時間数を表すことができます:
g.Sum(x => x.SOReputation.TotalHours)
これであなたが探している結果が得られると思いますが、必要なもの(時間、分、秒、日など)に応じて測定単位を入力する必要があることに注意してください。