Алгоритм поиска ближайшего времени - PullRequest
3 голосов
/ 08 мая 2019

У меня есть список значений DateTime с датами, которые содержат часы и минуты:

List<DateTime> times = times = new List<DateTime>()
{
    new DateTime(2019, 01, 01, 17, 00, 00),
    new DateTime(2019, 01, 01, 18, 45, 00),
    new DateTime(2019, 01, 01, 19, 00, 00),
    new DateTime(2019, 01, 01, 19, 30, 00),
    new DateTime(2019, 01, 01, 22, 30, 00)
};

DateTime current = DateTime.Now;

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

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

Например: если текущее время 17:32, оно выберет 17:00, потому что это самое близкое. Но если текущее время 18:20, оно выберет 18:45 и т. Д.

Ответы [ 5 ]

5 голосов
/ 08 мая 2019

Сравните со свойством Ticks DateTime ( MSDN ).Его можно рассматривать как линейное представление всей даты и отметки времени и можно сортировать.

Сделайте что-то вроде

comboBox.SelectedItem = times.OrderBy(t => Math.Abs(t.Ticks - current.Ticks)).First()
2 голосов
/ 08 мая 2019

Вы можете взять разницу с DateTime.Now для всех ваших дат, упорядочить по этой разнице и получить первый результат.

times.OrderBy(m => Math.Abs((DateTime.Now - m).TotalMilliseconds)).First();
0 голосов
/ 08 мая 2019

Один из вариантов - использовать MinBy от MoreLinq:

var actualNow = DateTime.Now;
// set `current` up however you need it
var current = new DateTime(2019, 01, 01, actualNow.Hour, actualNow.Minute, actualNow.Minute, actualNow.Millisecond); // set this up however you need it
var min = times.MinBy(z => Math.Abs((current - z).Ticks)).First();

Это позволяет избежать нагрузки на память решений на основе OrderBy (так как избегает выделения списка для хранениявесь набор times).

Обратите внимание, что вы можете проверить, является ли times пустым, прежде чем использовать это (или другие) решения.Если вы не хотите этого делать, рассмотрите возможность использования:

var min = times.MinBy(z => Math.Abs((current - z).Ticks)).Cast<DateTime?>().FirstOrDefault();

, который вернет null (вместо default(DateTime) или сгенерирует исключение), если times пусто.

0 голосов
/ 08 мая 2019

Вы ищете ArgMax, который не реализован в стандарте Linq , но может быть эмулирован с помощью Aggreagte

  List<DateTime> times = new List<DateTime>() {
    new DateTime(2019, 01, 01, 17, 00, 00),
    new DateTime(2019, 01, 01, 18, 45, 00),
    new DateTime(2019, 01, 01, 19, 00, 00),
    new DateTime(2019, 01, 01, 19, 30, 00),
    new DateTime(2019, 01, 01, 22, 30, 00),
  };

  DateTime toFind = new DateTime(2019, 5, 8, 18, 20, 0);

  var closestTime = times
    .Aggregate((best, item) => Math.Abs((item.TimeOfDay - toFind.TimeOfDay).Ticks) < 
                               Math.Abs((best.TimeOfDay - toFind.TimeOfDay).Ticks) 
       ? item 
       : best);

Обратите внимание, что если нам нужно найти ближайшее время , нам нужно избавиться от части даты - TimeOfDay. Если часть даты должна быть подсчитана, просто удалите TimeOfDay -

  var closestDateAndTime = times
    .Aggregate((best, item) => Math.Abs((item - toFind).Ticks) < 
                               Math.Abs((best - toFind).Ticks) 
       ? item 
       : best);
0 голосов
/ 08 мая 2019

Вам нужно будет выбрать экземпляр DateTime, который минимизирует временное расстояние до текущего времени.Вы можете использовать метод расширения для IEnumerable<T>, чтобы сделать это следующим образом.

public static T ArgMin<T, R>(T t1, T t2, Func<T, R> f)
                where R : IComparable<R>
{
    return f(t1).CompareTo(f(t2)) > 0 ? t2 : t1;
}

public static T ArgMin<T, R>(this IEnumerable<T> Sequence, Func<T, R> f)
                where R : IComparable<R>
{
    return Sequence.Aggregate((t1, t2) => ArgMin<T, R>(t1, t2, f));
}

var iNow = DateTime.Now;
var iResult = times.ArgMin(iTime => Math.Abs((iTime - iNow).Ticks));

Несмотря на то, что эта реализация очень общая, она не включает в себя какую-либо сортировку.

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