Linq очень медленный с предикатом и предложением по порядку - PullRequest
1 голос
/ 26 мая 2020

У нас есть List, содержащий 20K объектов, содержащих даты. Мы хотим найти самую последнюю дату из этого списка с учетом одного условия. Используя приведенный ниже код.

listObject.Where(r => r.Date <= asOfDate).OrderByDescending(r => r.Date).FirstOrDefault();

Это занимает слишком много времени, чем ожидалось. Не могли бы вы помочь, как лучше это сделать? Спасибо!

Ответы [ 5 ]

4 голосов
/ 26 мая 2020

Вы можете (на основе комментария @Barns)

var maxDate = listObject.Where(r => r.Date <= asOfDate).Max(r => r.date);
var item = listObject.FirstOrDefault(r => r.date == maxDate);

это будет только l oop над вашим списком дважды вместо его сортировки.

1 голос
/ 26 мая 2020

Попробуйте использовать Aggregate:

listObject
    .Where(r => r.Date <= asOfDate)
    .Aggregate((acc, curr) => curr.Date > acc.Date ? curr : acc)

С точки зрения производительности его можно улучшить, переместив лог c фильтрации внутри Aggregate и введя нулевой аккумулятор с нулевой обработкой внутри , но если производительность очень важна, просто переключитесь на for l oop.

0 голосов
/ 27 мая 2020

Почему бы не объединить операции Where и Max следующим образом:

var maxDate = listObject.Max(r => r.Date <= asOfDate ? r.Date : DateTime.MinValue);

var item = listObject.FirstOrDefault(r => r.date == maxDate);

Это будет выполняться по списку только дважды.

0 голосов
/ 26 мая 2020

Вы пробовали сначала отсортировать коллекцию?

listObject
.OrderByDescending(ordr => ordr.Date)
.Where(obj => obj.Date <= asOfDate)
.FirstOrDefault();
0 голосов
/ 26 мая 2020

В настоящее время у вас есть три операции:

.Where(r => r.Date <= asOfDate) - временная сложность O (n)

.OrderByDescending(r => r.Date) - временная сложность (я полагаю) O (n log (n))

.FirstOrDefault(); - временная сложность O (0)

Вы можете сделать следующее, чтобы получить тот же результат:

var maxDate= listObject.Where(r => r.Date <= asOfDate).Max(r => r.date); - временная сложность O (n)

var result = listObject.FirstOrDefault(r => r.Date == maxDate); - временная сложность O (n)

...