在输入日期之前在列表中查找最接近的日期

时间:2015-01-16 13:22:45

标签: c# date

我发现此代码用于查找日期范围内最接近的日期

    var inputDate = UserInputDate;
    List<DateTime> allDates = new List<DateTime>();
    allDates.add(date1);
    allDates.add(date2);
    allDates.add(date3);

    var closestDate = inputDate >= allDates.Last()
        ? allDates.Last()
        : inputDate <= allDates.First()
            ? allDates.First()
            : allDates.First(d => d >= inputDate);

但是,此代码会找到输入日期之后的最接近日期。

我需要的是inputDate之前最接近的日期

老实说,我不明白这段代码 我尝试将&gt; =更改为&lt; =和.Last更改为.First但它没有按照我想要的方式工作

3 个答案:

答案 0 :(得分:1)

如果列表已排序,您可以使用返回的BinarySearch函数

  

如果找到项目,则排序列表中项目的从零开始的索引;否则,负数是下一个元素的索引的按位补码,如果没有更大的元素,则是Count的按位补码。

int pos = allDates.BinarySearch(inputDate);
if (pos < 0)
    pos = ~pos - 1;

var closestDate = allDates[pos];

要解释你问题中的代码,它基本上是说

如果您要搜索的项目大于列表中的最后一个日期,请选择最后一项

var closestDate = inputDate >= allDates.Last()
? allDates.Last()

否则,如果输入日期低于第一项,请取第一项

: inputDate <= allDates.First()
    ? allDates.First()

否则,请将第一个项目大于或等于输入日期

: allDates.First(d => d >= inputDate);

如果您只想从您的问题中撤消逻辑,则需要最后一行才能使 last 项目小于您的输入。请注意,这仍然排序在列表仍然排序:

var closestDate = inputDate >= allDates.Last()
    ? allDates.Last()
    : inputDate <= allDates.First()
        ? allDates.First()
        : allDates.Last(d => d <= inputDate);

答案 1 :(得分:0)

我会通过构建一个小于输入日期的所有项目的过滤列表,然后取最大值来实现此目的:

var closestDate = allDates.Where(x => x < inputDate).DefaultIfEmpty().Max();

Where将过滤为仅保留小于inputDate的所有日期,Max将选择剩下的最大日期。

如果您认为该列表可能为空,则可以在DefaultIfEmpty()之前使用Max(如果列表为空,则会default(DateTime)作为结果。您可以也分开了:

var possibleDates = allDates.Where(x => x < inputDate);
if (possibleDates.Any())
{
    var closestDate = possibleDates.Max();
}

然而,如果allDates已在内存中排序,那么您可以这样做:

var closestDate = allDates.TakeWhile(x => x < inputDate).Last();

TakeWhile也会选择小于inputDate的元素,但会在找到更大的元素后停止。 (如果预先排序,这是有道理的。)

同样,要处理空列表,您可以使用LastOrDefault或与上述相同的Any模式。

答案 2 :(得分:-1)

命令他们降序,然后选择符合您标准的第一个:

var closest = allDates.OrderByDescending(x => x).First(x => x <= inputDate);