【问题标题】:Getting closest time获得最近的时间
【发布时间】:2013-02-25 22:55:44
【问题描述】:

我有一个对象列表,每个对象都有一个 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)

有什么优雅的方法可以做到这一点吗?

编辑:当然应该通过列表,抱歉。​​

【问题讨论】:

标签: c# .net


【解决方案1】:

您不妨创建一个中间列表(直接或间接)以提高速度:

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

【讨论】:

  • 这只是找到在原始时间之后的第一个条目......这与 最接近 的条目不同(例如,上午 8 点应该返回中午)。
  • @Jon Skeet:不完全是。我修改了时间,使它们正好在中间。只需找到中间之后的第一个即可找到正确的Name。添加了一个工作示例,它显示了正确的名称。
  • 啊,我明白了。是的,尽管 MyClass 中的值对于任何其他目的都是错误的......
【解决方案2】:

我假设您实际上也会传递列表?它的效率并不高,但基本上你想通过尝试现有时间和“下一次的同一时间”将每一对(从原始时间和“目标”时间)映射到 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

【讨论】:

  • 很抱歉,您的方法没有按我的需要工作。在最后一种情况下 (GetClosest(new TimeSpan(22, 0, 0));) 它将返回中午 (time-12),但我需要它返回最接近的时间,即午夜
  • @MAK:你到底是怎么期望它知道有哪些可用选项的?您在调用方法中声明您的列表,但没有在任何地方传递它。基本上,您最初提出的问题是不可能的。或者,如果您实际上是指晚上 10 点更接近午夜,那么您应该更具体地说明这一点 - 我可以尝试解决这个问题。
  • “或者,如果您实际上指的是接近午夜的晚上 10 点”- 正是我的意思,再次抱歉。
  • @MAK:是的,毕竟你打电话给GetClosest(new TimeSpan(22, 0, 0))。弄清楚这类事情真的很重要——你毕竟是在请求其他人帮助你。现在编辑它。
  • 谢谢你,乔恩,它按预期工作。你帮了我很大的忙。
猜你喜欢
  • 2019-04-16
  • 2021-05-17
  • 2018-10-09
  • 1970-01-01
  • 1970-01-01
  • 2021-09-05
  • 1970-01-01
  • 1970-01-01
  • 2011-04-13
相关资源
最近更新 更多