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);
这只会 运行 超过列表两次。
我们有包含 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);
这只会 运行 超过列表两次。