Найдите ближайшее время из списка раз

Итак, вот сценарий. У меня есть файл с созданным временем, и я хочу выбрать время из списка, когда время, созданное этим файлом, является самым близким или равным... что было бы лучшим способом для этого?

Ответы

Ответ 1

Что-то вроде этого:

DateTime fileDate, closestDate;
ArrayList theDates;
long min = long.MaxValue;

foreach (DateTime date in theDates)
 if (Math.Abs(date.Ticks - fileDate.Ticks) < min)
 {
   min = Math.Abs(date.Ticks - fileDate.Ticks);
   closestDate = date;
 }

Ответ 2

var closestTime = listOfTimes.OrderBy(t => Math.Abs((t - fileCreateTime).Ticks))
                             .First();

Если вам не нужны служебные издержки OrderBy, вы можете использовать что-то вроде MinBy метод расширения MoreLINQ вместо:

var closestTime = listOfTimes.MinBy(t => Math.Abs((t - fileCreateTime).Ticks));

Ответ 3

var closestTime = (from t in listOfTimes
                   orderby (t - fileInfo.CreationTime).Duration()
                   select t).First();

Ответ 4

Как часто вы будете делать это с тем же списком раз? Если вы делаете это только один раз, самым быстрым способом, вероятно, является просто просмотр списка и отслеживание ближайшего времени, которое вы видели. Когда/если вы встретите время, которое ближе, замените "ближайший" на это более близкое время.

Если вы делаете это очень часто, вы, вероятно, захотите отсортировать список, а затем использовать двоичный поиск.

Ответ 5

Принятый ответ совершенно неверен. Вы хотите что-то вроде этого:

  DateTime fileDate, closestDate;
  List<DateTime> theDates;

  fileDate = DateTime.Today;       //set to the file date
  theDates = new List<DateTime>(); //load the date list, obviously

  long min = Math.Abs(fileDate.Ticks - theDates[0].Ticks);
  long diff;
  foreach (DateTime date in theDates)
  {
    diff = Math.Abs(fileDate.Ticks - date.Ticks);
    if (diff < min)
    {
      min = diff;
      closestDate = date;
    }
  }

Ответ 6

Получите разницу в креате файла и каждый раз в своем списке и сортируйте абсолютное значение каждой разницы во времени. первым должен быть ответ, который вы ищете.

Ответ 7

Используйте минимальную абсолютную разницу во времени между временем файла и временем в списке. Вы можете сделать две записи одинаковыми, и тогда вам понадобится другой метод, чтобы отличаться от них.

Ответ 8

Не ответ, а вопрос о различных решениях LINQ, предложенных выше. Насколько эффективен LINQ? Я еще не писал никаких "реальных" программ с LINQ, поэтому я не уверен в производительности.

В этом примере коллекция "listOfTimes" подразумевает, что мы уже выполнили итерацию над некоторыми объектами на основе файловой системы, чтобы собрать время. Было бы более эффективно выполнять анализ во время итерации, а не позже в LINQ? Я признаю, что эти решения могут быть более "изящными" или красиво абстрагироваться от идеи "коллекция как база данных", но я склонен выбирать эффективность (должен быть удобочитаемым) по сравнению с моим программированием. Просто интересно, может ли стоимость LINQ перевесить элегантность здесь?

Ответ 9

var creationTimes = new [] {DateTime.Now.AddDays(-1), DateTime.Now.AddDays(-2)};
FileInfo fi = new FileInfo("C:/test.xml");
var closestTime = creationTimes
    .OrderBy(c => Math.Abs(c.Subtract(fi.CreationTime).Days))
    .First();

Ответ 10

var min = listoftimes.Select(
    x => new { diff = Math.Abs((x - timeoffile).Ticks), time = x}).
    OrderBy(x => x.diff).
    First().time;

Примечание. Предполагается, что как минимум 1 запись в listoftimes.

Ответ 11

Мне показалось, что я бы обновил этот пост, чтобы включить сценарий реального мира. Мне нужна такая функция, поскольку у меня есть блог с новостями о последних фильмах.

Однако я не хочу перечислять скрининг в прошлом (например, дату скрининга за текущую дату), и поскольку я хотел показать запись, мне нужен был какой-то идентификатор, переданный для записи записи.

Я оставил, если просто, чтобы вы могли следить за процессом и, без сомнения, сделать его более эффективным с LINQ и др.

Сначала модель

        public class LatestScreeeningsModel
    {
        public int Id { get; set; }
        public DateTime Date { get; set; }
    }

Затем блок кода, который вы можете вызвать с вашего контроллера

        private static LatestScreeeningsModel GetLatestScreening(IPublishedContent currentNode)
    {
        LatestScreeeningsModel latestScreening = new LatestScreeeningsModel();

        DateTime fileDate;

        // get a list of screenings that have not shown yet
        var screenings = currentNode.AncestorsOrSelf("siteLanguage")
                                   .FirstOrDefault().Descendants("screening")
                                   .Select(x => new LatestScreeeningsModel() { Id = x.Id, Date = x.GetPropertyValue<DateTime>("date") })
                                   .Where(x => x.Date > DateTime.Now).ToList();

        fileDate = DateTime.Today;

        long min = Math.Abs(fileDate.Ticks - screenings[0].Date.Ticks);
        long diff;
        foreach (var comingDate in screenings)
        {
            diff = Math.Abs(fileDate.Ticks - comingDate.Date.Ticks);
            if (diff <= min)
            {
                min = diff;
                latestScreening = comingDate;
            }
        }

        return latestScreening;

    }

Я использую Umbraco для получения элементов даты, но он будет работать с любой настраиваемой моделью, List et al.

Надеюсь, что это поможет