简体   繁体   English

从DateTime列表中找到最接近的上一个DateTime

[英]Find the closest previous DateTime from a list of DateTime

Is there a faster way of obtaining the closest previous (past) DateTime from a list of DateTimes when compared to a specific time? 与特定时间相比,是否有更快的方法从DateTime列表中获取最接近的上一个(过去)DateTime? (the list comes from a SQL database) (该列表来自SQL数据库)

public DateTime GetClosestPreviousDateTime(List<DateTime> dateTimes, DateTime specificTime)
{
    DateTime ret = null;
    var lowestDifference = TimeSpan.MaxValue;

    foreach (var date in dateTimes)
    {
        if (date >= specificTime)
            continue;

        var difference = specificTime- date;

        if (difference < lowestDifference)
        {
            lowestDifference = difference;
            ret = date;
        }
    }

    return ret;
}

The source list will be sorted since the dates in the list come from a SQL database where they are written consecutively. 源列表将被排序,因为列表中的日期来自连续写入日期的SQL数据库。

It depends what you mean by "faster". 这取决于您所说的“更快”。 The algorithm you show is O(N) so no you won't get faster than that - if by faster you mean is there a way to not have to iterate over all dates. 您显示的算法为O(N),所以不会,您不会比这更快-如果更快,您的意思是有一种不必遍历所有日期的方法。

But if you mean can you shave off a few microseconds with some code that doesn't emit quite as many op codes, then yes of course. 但是,如果您的意思是您可以用一些不会发出那么多操作码的代码来节省几微秒的时间,那么当然可以。 But is that really the issue here? 但这真的是这里的问题吗?

The answer will also change based on the size of the list, how accurate you need the answer to be, whether we can make any assumptions on the data (eg is it already sorted). 答案还将根据列表的大小,所需答案的准确性,我们是否可以对数据做出任何假设(例如,是否已对其进行排序)而变化。

dateTimes.Where(x => x < specificTime).Max()

or if you want to handle the case where none exist: 或者,如果您要处理不存在的情况:

dateTimes.Where(x => x < specificTime).DefaultIfEmpty().Max()

Later edit: Now you introduce new information that the List<> is already sorted. 以后的编辑:现在,您将介绍List<>已被排序的新信息。 That was not in the question before. 那不是以前的问题。

With a sorted List<> , your algorithm is silly since it foreach es on and on, even after having reached the point where the entries "pass" the threshold specificTime . 使用排序后的List<> ,即使到达条目“超过”阈值specificTime的点,您的算法foreach连续不断地进行,因此它是愚蠢的。 You can use instead BinarySearch (assuming List<> is sorted in ascending order and contains no duplicates ): 您可以改用BinarySearch (假设List<>升序排序, 并且不包含重复项 ):

static DateTime GetClosestPreviousDateTime(List<DateTime> dateTimes, DateTime specificTime)
{
  var search = dateTimes.BinarySearch(specificTime);
  var index = (search < 0 ? ~search : search) - 1;
  if (index == -1)
    throw new InvalidOperationException("Not found");
  return dateTimes[index];
}

If you want to do it faster, just ask the database for the value, it will know how to find the answer fast; 如果您想更快地执行此操作,只需向数据库询问值,它将知道如何快速找到答案。 do not fetch the entire List<> to memory first. 不要先获取整个List<>到内存。 Use SQL or LINQ to the database. 使用SQL或LINQ到数据库。

Your problem is a classic search algorithm and binary search might suit you. 您的问题是经典搜索算法,二进制搜索可能适合您。

  1. Sort list: dateTimes.Sort(); 排序列表: dateTimes.Sort();
  2. Apply Binary Search algo with similar logic as in your for statement. 应用与for语句中类似的逻辑应用二进制搜索算法。
dateTimes.Sort();
var closest = dateTimes[dateTimes.IndexOf(search) - 1];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM