Find next closest date

佐手、 提交于 2019-12-01 22:55:46

问题


I have some dates which are currently stored as a list of strings.

For example:

List<string> dates = new List<string>();
dates.Add("1/10/14");
dates.Add("2/9/14");
dates.Add("1/15/14");
dates.Add("2/3/14");
dates.Add("2/15/14");

(The date is in mm/dd/yy format)

I will take a user's input (also in mm/dd/yy format), but as a string.

Now, I want to find the date in the array that is the next closest after the user input date.

For example, if the user enters "1/13/14", the output should be "1/15/14". If the user enters "2/5/14", then the next closest date is "2/9/14". But if the user enter a date that is later than the last date (say "3/1/14", it will STILL return the last date in the array which is "2/15/14")

I know at some point you have to convert to type DateTime, but I couldn't figure out the logic to find such date.


回答1:


List<string> dates = new List<string>();
            dates.Add("1/10/14");
            dates.Add("2/9/14");
            dates.Add("1/15/14");
            dates.Add("2/3/14");
            dates.Add("2/15/14");

            var allDates = dates.Select(DateTime.Parse).OrderBy(d=>d).ToList();
            var inputDate = DateTime.Parse("1/13/14");

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

For now I'm just parsing strings, but you should handle it separately. This is simple plain LINQ, you can go fancy and do binary search as well.




回答2:


Here is a solution that uses a Binary Search.

You need to have a list of DateTimes, no question about it. No point in keeping them as strings, parse them on the way into the list if you have to. You can use LINQ to convert all the elements in the list, but that's the only way you'll be able to compare dates with eachother.

Check out the page for BinarySearch to understand why I am using the bitwise operator on the return value.

//build list of random dates
Random r = new Random();
var dates = new List<DateTime>();
for (int i = 0; i < 10; i++)
{
    dates.Add(new DateTime(2014, r.Next(1,13), r.Next(1,28)));
}

//sort list (if you don't do this, you'll most likely get the wrong answer)
dates.Sort();

//get input
string input = "1/13/14";
DateTime inputDate = DateTime.Parse(input);

//find nearest
var result = dates.BinarySearch(inputDate);
DateTime nearest;

//get match or next in list.
if(result >= 0)
    nearest = dates[result];
else if (~result == dates.Count )
    nearest =dates.Last();
else
    nearest = dates[~result];

If you need to find the true closest, use this in place of the last if block.

//get match, or true nearest date in list
if(result >= 0)                   //date was found! Use that index.
    nearest = dates[result];
else if (~result == 0)            //date not found, smaller than any item in the list. use first index.
    nearest = dates.First();
else if(~result == dates.Count)   //date was not found, and is greater than all items. Use last index.
    nearest = dates.Last();
else                              //date not found, somewhere in the middle of the list. find the nearest date                              
{
    var daysAfter = dates[~result].Subtract(inputDate);      //date after input
    var daysBefore = inputDate.Subtract(dates[~result - 1]); //date before input
    if(daysAfter < daysBefore)
        nearest = dates[~result];
    else
        nearest = dates[~result - 1];
}



回答3:


DateTime searchDate = new DateTime(2014,03,01);

var orderedDates = dates
.Select(d => DateTime.ParseExact(d, "M/d/yy", CultureInfo.InvariantCulture))
.OrderBy(d => d).ToList();

var result = orderedDates.FirstOrDefault(d => d > searchDate);
if (result == default(DateTime))
  result = orderedDates.Last();



回答4:


Something like this?

List<string> dates   = YourListOfStringsHere() ; // list of strings in MM/dd/yyyy form.
DateTime desiredDate = new DateTime(2014,2,27) ;
DateTime foundDate   = dates
                       .Select( x => DateTime.ParseExact(x,"MM/dd/yyyy",CultureInfo.CurrentCulture))
                       .Where( x => x >= desiredDate.Date )
                       .Min()
                       ;

Why you'd be storing date/time values as a string is beyond me. When you load them, why not convert them? That way, they're easier to manipulate, you know you've got clean data. Everything becomes much simpler.



来源:https://stackoverflow.com/questions/22208245/find-next-closest-date

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!