C#中TimeSpans的总和

fre*_*hie 43 c# linq timespan

我有一组包含TimeSpan变量的对象:

MyObject
{ 
    TimeSpan TheDuration { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我想用LINQ来总结这些时间.当然,(来自MyCollection中的r选择r.TheDuration).Sum(); 不起作用!

我正在考虑将TheDuration的数据类型更改为int,然后将其求和并将总和转换为TimeSpan.这将是混乱的,因为我的集合中的每个TheDuration都用作其他地方的时间跨度.

有关此总结的任何建议?

Ani*_*Ani 103

不幸的是,没有一个超载Sum接受了IEnumerable<TimeSpan>.此外,目前没有为类型参数指定基于运算符的通用约束的方法,因此即使TimeSpan"本机"可求和,通用代码也无法轻易获取该事实.

一种选择是,如你所说,总结一个等同于时间跨度的积分型,然后再将这个总和变成一个TimeSpan.理想的属性是TimeSpan.Ticks,准确地往返.但是根本没有必要改变你班级的属性类型; 你可以投射:

var totalSpan = new TimeSpan(myCollection.Sum(r => r.TheDuration.Ticks));
Run Code Online (Sandbox Code Playgroud)

或者,如果您想坚持使用TimeSpan的+运算符进行求和,您可以使用Aggregate运算符:

var totalSpan = myCollection.Aggregate
                (TimeSpan.Zero, 
                (sumSoFar, nextMyObject) => sumSoFar + nextMyObject.TheDuration);
Run Code Online (Sandbox Code Playgroud)

  • 只是一个小的修正。它应该是 `var totalSpan = new TimeSpan(myCollection.Sum(r =&gt; r.Ticks)); 如果`myCollection 是`List&lt;TimeSpan&gt;()`。 (2认同)

gra*_*tnz 38

这很好用(基于Ani答案的代码)

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

用法:

如果Periods是具有Duration属性的对象列表

TimeSpan total = Periods.Sum(s => s.Duration)
Run Code Online (Sandbox Code Playgroud)


Mat*_*ams 5

我相信这是最干净的 LINQ 扩展:

public static class LinqExtensions
{
    public static TimeSpan Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, TimeSpan> func)
    {
        return new TimeSpan(source.Sum(item => func(item).Ticks));
    }
}
Run Code Online (Sandbox Code Playgroud)

用法是一样的:

TimeSpan total = Periods.Sum(s => s.Duration)
Run Code Online (Sandbox Code Playgroud)