Найдите ближайшее время из списка раз
Итак, вот сценарий. У меня есть файл с созданным временем, и я хочу выбрать время из списка, когда время, созданное этим файлом, является самым близким или равным... что было бы лучшим способом для этого?
Ответы
Ответ 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.
Надеюсь, что это поможет