Найти ближайшее время из списка раз - PullRequest
19 голосов
/ 18 ноября 2009

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

Ответы [ 11 ]

46 голосов
/ 18 ноября 2009
var closestTime = listOfTimes.OrderBy(t => Math.Abs((t - fileCreateTime).Ticks))
                             .First();

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

var closestTime = listOfTimes.MinBy(t => Math.Abs((t - fileCreateTime).Ticks));
8 голосов
/ 01 декабря 2009

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

  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;
    }
  }
8 голосов
/ 18 ноября 2009

Примерно так:

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;
 }
6 голосов
/ 18 ноября 2009
var closestTime = (from t in listOfTimes
                   orderby (t - fileInfo.CreationTime).Duration()
                   select t).First();
5 голосов
/ 18 ноября 2009

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

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

2 голосов
/ 18 ноября 2009

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

1 голос
/ 18 ноября 2009

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

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

1 голос
/ 18 ноября 2009

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

0 голосов
/ 28 января 2017

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

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

Я оставил, если все просто, чтобы вы могли следить за процессом и, несомненно, сделать его более эффективным с помощью 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.

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

0 голосов
/ 18 ноября 2009
var min = listoftimes.Select(
    x => new { diff = Math.Abs((x - timeoffile).Ticks), time = x}).
    OrderBy(x => x.diff).
    First().time;

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

.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...