我有一组包含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)
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)
我相信这是最干净的 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)