Linq 对于谓词和 order by 子句非常慢

Linq is very slow with predicate and order by clause

我们有包含 20K 个对象的列表,其中包含日期。考虑到一个条件,我们想从该列表中找到最近的日期。使用代码如下。

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

这花费的时间比预期的要长。 你能帮忙做一下更好的方法吗? 谢谢你!

你可以做到(基于@Barns 评论)

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

这只会循环遍历您的列表两次,而不是对其进行排序。

您目前有三个操作:

.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)

您尝试过先对集合进行排序吗?

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

尝试使用 Aggregate:

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

在性能方面,可以改进 Aggregate 中的移动过滤逻辑并在内部引入具有空处理的空累加器,但如果性能是一个大问题,只需切换到 for 循环。

为什么不像这样结合 Where 和 Max 操作:

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

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

这只会 运行 超过列表两次。