【问题标题】:Linq is very slow with predicate and order by clauseLinq 对于谓词和 order by 子句非常慢
【发布时间】:2020-05-26 16:38:17
【问题描述】:

我们的 List 包含 20K 个对象,其中包含日期。考虑到一种情况,我们希望从该列表中找到最近的日期。使用代码如下。

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

这比预期花费的时间太长。 你能帮忙看看有什么更好的方法吗? 谢谢!

【问题讨论】:

  • 您是否尝试过类似:var max = listObject.Where(r =&gt; r.Date &lt;= asOfDate).Max();
  • 列表中还有一些其他属性,max 将只给我们 Date 对象
  • 常规的for 循环怎么样?
  • 只是出于好奇,列表的内容是什么?数据库?既然你提到了 Linq-to-Entities
  • 这个列表是从计算器生成的,完整的 C# 列表

标签: c# linq linq-to-entities


【解决方案1】:

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

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

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

【讨论】:

  • 如果我没记错的话,在 linq to objects 的情况下,它最多会循环 3 次,具体取决于过滤掉的对象数量。
【解决方案2】:

尝试使用Aggregate

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

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

【讨论】:

    【解决方案3】:

    您目前有三个操作:

    .Where(r =&gt; r.Date &lt;= asOfDate) - 时间复杂度 O(n)

    .OrderByDescending(r =&gt; r.Date)- 时间复杂度(我想)O(n log(n))

    .FirstOrDefault();- 时间复杂度 O(0)

    您可以执行以下操作以获得相同的结果:

    var maxDate= listObject.Where(r =&gt; r.Date &lt;= asOfDate).Max(r =&gt; r.date); - 时间复杂度 O(n)

    var result = listObject.FirstOrDefault(r =&gt; r.Date == maxDate); - 时间复杂度 O(n)

    【讨论】:

      【解决方案4】:

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

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

      这只会在列表中运行两次。

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

        • 这只是意味着订购更长的列表 - 我希望它会更慢。
        猜你喜欢
        • 1970-01-01
        • 2012-01-28
        • 2011-02-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多