прошу помочь составить Linq запрос
List<DateTime> j = new List<DateTime>();
в нем неизвестное кол-во елементов со значением дат. в формате "year-month-day" нужно в новую переменную вытащить дату наиболее близкую к сегодняшней.
тоесть если в листе 2018-11-30, 2018-12-01, 2018-12-02,
то должно вытянуть 2018-12-2
Я думаю, что что-то типа этого:
List<DateTime> j = new List<DateTime>();
var nowDate=DateTime.Now;
j.Select(date => new {Secs = Math.Abs((nowDate - date).TotalSeconds), Date = date})
.OrderBy(x => x.Secs).First();
Логика
Я вычитаю из текущий даты, дату каждого элемента, а затем перевожу в секунды.
На основании этого я делаю анонимный класс Secs-секунды и Date-DateTime из вашего списка.
Далее, я сортирую по секундам по возрастанию. Очевидно, что элемент, где меньше всего секунд и будет нужным нам элементом. Так как мы выполнили сортировку, то он должен быть первым.
А возвращает 2 значения из-за того, что был создан анонимный класс с вспомогательным полем по которому мы выполнили сортировку. Можно просто взять элемент DateTime и присвоить в другую переменную.
Как альтернативный вариант, можно сделать так:
List<DateTime> j = new List<DateTime>();
var nowDate=DateTime.Now;
j.OrderBy(date => Math.Abs((nowDate - date).TotalSeconds)).First();
Альтернативным решением может быть использование метода Aggregate, это позволит найти значение с минимальным отклонением за один проход.
Для этого нужно задать начальное состояние, в котором хранить выбранную дату и ее разницу с Now.
new { Diff = TimeSpan.MaxValue, Date = new DateTime(0) }
В самом методе необходимо вычислить разницу между текущим элементом и Now
, и получить ее абсолютное значение. Для этого можно воспользоваться методом .Duration
var diff = (cur - now).Duration();
Если полученная разница больше сохраненной, вернуть сохраненную, если меньше - вернуть новую.
return (diff <= acc.Diff) ? new { Diff = diff, Date = cur } : acc
Чтобы в результате получить только дату, нужно добавить третий параметр, который показывает как определять результат, в данном случае нужно просто вернуть поле Date
acc => acc.Date
Все в сборе может выглядеть так:
var now = DateTime.UtcNow;
var result = j.Aggregate(new { Diff = TimeSpan.MaxValue, Date = new DateTime(0) }, (acc, cur) =>
{
var diff = (cur - now).Duration();
return (diff <= acc.Diff) ? new { Diff = diff, Date = cur } : acc
}, acc => acc.Date);
Есть популярная библиотека MoreLinq, с большим набором методов расширений. Предлагаю воспользоваться ей: решение будет лаконичным и понятным.
using MoreLinq;
var now = DateTime.Now;
var near = j.MinBy(date => Math.Abs((now - date).Ticks)).First();
По сути это тот же алгоритм, что в ответе iluxa1810.
И я думаю, что лучше использовать целочисленное свойство Ticks
.
var now = DateTime.Now;
j.Aggregate(DateTime.MaxValue, (acc, next) => {
var prevDiff = Math.Abs((now - acc).TotalHours);
var currentDiff = Math.Abs((now - next).TotalHours);
return prevDiff <= currentDiff ? acc : next;
});
Виртуальный выделенный сервер (VDS) становится отличным выбором
Как при помощи метода FileStreamSeek считать часть массива байт от всего массива?
Всем привет, наверно я уже надоел) задаю и задаю вопросыЯ и не знаю как правильно задать этот вопрос
Можете подсказать как занести данные в SQL цикломНапример: я получаю циклом данные из 1С и эти данные занести в SQL