I have a collection of objects that include a TimeSpan variable:
MyObject { TimeSpan TheDuration { get; set; } }
I want to use LINQ to sum those times. Of course, (from r in MyCollection select r.TheDuration).Sum(); doesn't work!
I'm thinking of changing the datatype of TheDuration to an int and then summing it and converting the sum to a TimeSpan. That will be messy because each TheDuration in my collection is used in as a timespan somewhere else.
Any suggestion on this summation?
This C# program is used to add two timespan using 's1' and 's2' variables respectively. Here the two timespans are added using 's3' variable, returns a new TimeSpan object whose value is the sum of the specified TimeSpan object and this instance. Sanfoundry Global Education & Learning Series – 1000 C# Programs.
It should be var totalSpan = new TimeSpan(myCollection. Sum(r => r. Ticks)); in case if myCollection is List<TimeSpan>() .
Unfortunately, there isn't a an overload of Sum
that accepts an IEnumerable<TimeSpan>
. Additionally, there's no current way of specifying operator-based generic constraints for type-parameters, so even though TimeSpan
is "natively" summable, that fact can't be picked up easily by generic code.
One option would be to, as you say, sum up an integral-type equivalent to the timespan instead, and then turn that sum into a TimeSpan
again. The ideal property for this is TimeSpan.Ticks
, which round-trips accurately. But it's not necessary to change the property-type on your class at all; you can just project:
var totalSpan = new TimeSpan(myCollection.Sum(r => r.TheDuration.Ticks));
Alternatively, if you want to stick to the TimeSpan's +
operator to do the summing, you can use the Aggregate
operator:
var totalSpan = myCollection.Aggregate (TimeSpan.Zero, (sumSoFar, nextMyObject) => sumSoFar + nextMyObject.TheDuration);
This works well (code based on Ani's answer)
public static class StatisticExtensions { public static TimeSpan Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, TimeSpan> selector) { return source.Select(selector).Aggregate(TimeSpan.Zero, (t1, t2) => t1 + t2); } }
Usage :
If Periods is a list of objects with a Duration property
TimeSpan total = Periods.Sum(s => s.Duration)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With