【问题标题】:LINQ Query - nearest adjacent dateLINQ 查询 - 最近的相邻日期
【发布时间】:2017-06-12 23:17:01
【问题描述】:

我正在尝试编写一种方法,该方法将在给定日期列表和目标日期的情况下按时间顺序确定最接近的日期。例如,给定(简化的)日期集 {Jan 2011, March 2011, November 2011},目标日期为 2011 年 4 月,该方法将返回 2011 年 3 月

起初,我正在考虑使用 LINQ 的跳过,但我不确定合适的 Func 是否会在超过日期之前停止之前。下面这似乎是一个可行的解决方案,但我不确定是否有更有效的方法来做到这一点。大概 Last 和 First 都是线性时间。

源数据集可以介于 0 到 10,000 个日期之间,一般在 5,000 个左右。此外,我将整个过程迭代 5 到 50 次(这是不同迭代的目标日期数)。

// assume dateSet are ordered ascending in time.
public DateTime GetClosestDate(IEnumerable<DateTime> dateSet, DateTime targetDate)
{
   var earlierDate = dateSet.Last(x => x <= targetDate);
   var laterDate = dateSet.First(x => x >= targetDate);

   // compare TimeSpans from earlier to target and later to target.
   // return closestTime;
}

【问题讨论】:

    标签: c# .net linq


    【解决方案1】:

    好吧,使用来自MoreLINQMinBy

    var nearest = dateSet.MinBy(date => Math.Abs((date - targetDate).Ticks);
    

    换句话说,对于每个日期,通过从另一个日期减去一个日期(无论哪种方式),在结果 TimeSpan 中获取 Ticks 的数量,并找到绝对值,找出它的距离。选择该差异的结果最小的日期。

    如果你不能使用 MoreLINQ,你可以自己写一些类似的东西,或者分两步完成(blech):

    var nearestDiff = dateSet.Min(date => Math.Abs((date - targetDate).Ticks));
    var nearest = dateSet.Where(date => Math.Abs((date - targetDate).Ticks) == nearestDiff).First();
    

    【讨论】:

    • 如果没有 MoreLINQ,同样的算法也可以用于其他一些 LINQ 表达式:return dateSet.OrderBy(date =&gt; Math.Abs((date - targetDate).Ticks).First();
    • 我宁愿不将 MoreLINQ 作为依赖项引入,但似乎是一个漂亮的项目。您和 esker 的回复给了我我所需要的东西。谢谢。
    • @esker:可以做到——但它需要 O(N) 内存和 O(N log N) 时间,而不是 O(1) 内存和 O(N) 时间。这从根本上是不优雅的,IMO :) 但是,是的,它可能就是所需要的......
    • @Skeet,你在说什么是“O(1) 内存和 O(N)”?您的解决方案,还是使用 MinBy?
    • @Stealth Rabbi:O(2n) == O(n),只是常数因子不同。
    【解决方案2】:

    使用 Last 和 First 迭代 dateSet 两次。您可以使用自己的逻辑自己迭代 dateSet。这会更有效率,但除非您的 dateSet 非常大或枚举 dateSet 由于某些其他原因非常昂贵,否则速度上的一点点增益可能不值得编写更复杂的代码。首先,您的代码应该易于理解。

    【讨论】:

    • 源数据集可以在0到10000个日期之间,一般在5000个左右。此外,我将整个过程迭代 5 到 50 次(这是不同迭代的目标日期数)。我将其添加到描述中
    猜你喜欢
    • 2016-04-19
    • 1970-01-01
    • 2014-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    相关资源
    最近更新 更多