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

时间:2017-12-22 19:19:06

标签: c# linq datetime

与特定时间相比,是否有更快的方法从DateTimes列表中获取最接近的上一个(过去)DateTime? (该列表来自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;
}

源列表将被排序,因为列表中的日期来自连续写入它们的SQL数据库。

4 个答案:

答案 0 :(得分:3)

这取决于你所说的“更快”。您显示的算法是O(N),所以不会比这更快 - 如果你的意思更快,那么就有办法不必迭代所有日期。

但是如果你的意思是你可以用一些不会发出相同数量的操作码的代码来削减几微秒,那么当然是的。但这真的是问题吗?

答案也将根据列表的大小,您需要答案的准确程度,我们是否可以对数据做出任何假设(例如它已经排序)来改变。

答案 1 :(得分:0)

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

或者如果你想处理不存在的情况:

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

稍后编辑:现在您介绍List<>已经排序的新信息。这不是以前的问题。

对于已排序的List<>,您的算法是愚蠢的,因为它foreach依次开启,即使在达到条目&#34;通过&#34;之后也是如此。阈值specificTime。您可以使用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];
}

如果你想更快地做到这一点,只需向数据库询问价值,就会知道如何快速找到答案;不要先将整个List<>提取到内存中。使用SQL或LINQ到数据库。

答案 2 :(得分:0)

您的问题是一种经典的搜索算法,二进制搜索可能适合您。

  1. 排序列表:dateTimes.Sort();
  2. 使用与for语句类似的逻辑应用二进制搜索算法。

答案 3 :(得分:0)

element.style.cursor