最接近时间

本文关键字:时间 最接近 | 更新日期: 2023-09-27 18:03:09

我有一个对象列表,每个对象都有一个TimeSpan属性表示一天中的时间。我需要得到一个时间最接近输入值的对象

应该是这样的…

List<MyClass> list = new List<MyClass>
{
   new MyClass() {Name="midnight", time= new TimeSpan(0,0,0)},
   new MyClass() {Name="noon", time= new TimeSpan(12,0,0)},
};
var testOne = GetClosest(new TimeSpan(2, 0, 0),list); // returns midnight
var testTwo = GetClosest(new TimeSpan(8, 0, 0),list); // returns noon
var testThree = GetClosest(new TimeSpan(13, 0, 0),list); // returns noon
var testFour = GetClosest(new TimeSpan(22, 0, 0),list); // returns midnight (that's the tricky one)

是否有一些优雅的方法来做到这一点?

编辑:当然应该传递列表,对不起。

最接近时间

我假设你实际上也会传递列表?这并不是很有效,但基本上你希望通过尝试现有时间和"第二天同一时间"将每对时间(从原始时间和"目标"时间)映射到0到12小时的范围内。例如:

public static TimeSpan GetClosest(TimeSpan time, IEnumerable<TimeSpan> targets)
{
    return targets.OrderBy(x => BestFit(x, time))).First();
}
private static long BestFit(TimeSpan x, TimeSpan y)
{
    return Math.Min(Math.Abs((x - y).TotalTicks,
                    Math.Abs((x + TimeSpan.FromDays(1) - y).TotalTicks));
}

或者使用MoreLINQ来避免完整排序,但保持简单(甚至更简单)的代码:

public static TimeSpan GetClosest(TimeSpan time, IEnumerable<TimeSpan> targets)
{
    return targets.MinBy(x => BestFit(x, time));
}
// BestFit as before

您不妨创建一个中间列表(直接或间接)以获得额外的速度:

public static string GetFirstEqualOrHigher(TimeSpan time, IEnumerable<MyClass> targets)
{
    return list.First(x => time >= x.time).Name;
}
IList<MyClass> list = new List<MyClass>
{
    new MyClass() { Name="midnight", time = new TimeSpan(18, 0, 0) }
    new MyClass() { Name="noon", time = new TimeSpan(6, 0, 0) },
    new MyClass() { Name="midnight", time = new TimeSpan(0, 0, 0) },
};
var testOne = GetFirstEqualOrHigher(new TimeSpan(2, 0, 0), list); // returns midnight
var testTwo = GetFirstEqualOrHigher(new TimeSpan(8, 0, 0), list); // returns noon
var testThree = GetFirstEqualOrHigher(new TimeSpan(13, 0, 0), list); // returns noon
var testFour = GetFirstEqualOrHigher(new TimeSpan(22, 0, 0), list); // returns midnight (that's the tricky one