Sea*_*ech 9 .net c# linq datetime timespan
是否有一个优雅的解决方案来遍历有序列表,对当前和下一个对象进行一些计算?LINQ必须有一个更聪明的方法来执行以下操作:
public static List<double> GetHoursBetweenDates(List<DateTime> aDates)
{
List<double> lst = new List<double>();
var olst = aDates.OrderByDescending(d => d).ToList();
for (int i = 0; i < olst.Count - 1; i++)
{
lst.Add(olst[i].Subtract(olst[i+1]).TotalHours);
}
return lst;
}
Run Code Online (Sandbox Code Playgroud)
p.s*_*w.g 11
最简单的比较列表中的每个连续元素是这样的:
var sorted = aDates.OrderByDescending(d => d);
var results =
sorted.Zip(sorted.Skip(1), (a, b) => a.Subtract(b).TotalHours);
Run Code Online (Sandbox Code Playgroud)
或者,您可以这样做:
var sorted = aDates.OrderByDescending(d => d).ToArray();
var results =
from i in Enumerable.Range(0, sorted.Length - 1)
select sorted[i].Subtract(sorted[i + 1]).TotalHours;
Run Code Online (Sandbox Code Playgroud)
但是第二种方法只能工作List<T>,T[]或任何支持数组样式索引器的类型.
作为使用LINQ Zip枚举器的解决方案的替代方案,它需要您对列表进行两次迭代,这里是一个自定义LINQ运算符,它迭代序列并返回一个"移动对"元素:
static IEnumerable<Tuple<T, T>> Pairwise<T>(this IEnumerable<T> xs)
{
using (IEnumerator<T> enumerator = xs.GetEnumerator())
{
if (!enumerator.MoveNext()) yield break;
T current = enumerator.Current;
while (enumerator.MoveNext())
{
T previous = current;
current = enumerator.Current;
yield return Tuple.Create(previous, current);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以将其应用于您的DateTime序列,如下所示:
dates.Pairwise().Select(_ => _.Item2.Subtract(_.Item1).TotalHours);
Run Code Online (Sandbox Code Playgroud)
其他选项是使用Aggregate函数,并作为聚合返回当前元素.这样做的另一个好处是只迭代集合一次:
public static List<double> GetHoursBetweenDates(List<DateTime> aDates)
{
List<double> lst = new List<double>();
aDates.OrderByDescending(d => d).Aggregate((prev, curr) => { lst.Add(prev.Subtract(curr).TotalHours); return curr; });
return lst;
}
Run Code Online (Sandbox Code Playgroud)
您可以使用moreLINQ库中的Incremental扩展方法:
public static List<double> GetHoursBetweenDates(List<DateTime> aDates)
{
return aDates.OrderByDescending(d => d)
.Incremental((p,n) => p.Subtract(n).TotalHours)
.ToList();
}
Run Code Online (Sandbox Code Playgroud)
它完全符合您的需求:
/// <summary>
/// Computes an incremental value between every adjacent element in a sequence: {N,N+1}, {N+1,N+2}, ...
/// </summary>
/// <remarks>
/// The projection function is passed the previous and next element (in that order) and may use
/// either or both in computing the result.<
/// If the sequence has less than two items, the result is always an empty sequence.
/// The number of items in the resulting sequence is always one less than in the source sequence.
/// </remarks>
Run Code Online (Sandbox Code Playgroud)