【问题标题】:LINQ Contains vs Intersect (vs anything else!)LINQ 包含与相交(与其他任何东西相比!)
【发布时间】:2013-12-30 06:00:21
【问题描述】:

我有一个大型 IEnumerable EntityObjects 和一个大型 IEnumerable 字符串,它们是对象的键。

我想获得一个只包含匹配键的对象的新列表。目前我正在通过Contains() 执行此操作 - 但它似乎很慢?

class Foo {
  string Key
  string Prop1
  int Prop2
  decimal Prop3
  Bar Prop4
  Thing Prop5
  Stuff Prop6
  ...more properties
}

IEnumerable<Foo> foos
IEnumerable<string> fooKeys

var matchedFoos = foos.Where(f => fooKeys.Contains(f.Key));

这工作并返回我所期望的,但似乎很慢,我认为必须有更好的方法?我看过一些关于 Intersect 的帖子,但似乎是针对同一类型的枚举的?

信息:

  • foos.Count() 约 164,000
  • fooKeys.Count() 约 75,000

【问题讨论】:

    标签: c# performance linq ienumerable


    【解决方案1】:
    1. 您可能应该对数据库进行搜索(使用 LINQ to Entities),而不是应用程序(使用 LINQ to Objects)。

    2. 您可以将fooKeys 更改为HashSet&lt;string&gt;(如果它还不是)以使Contains() 方法调用O(1) 而不是O(n)

      var keesSet = new HashSet<string>(fooKeys);
      var matchedFoos = foos.Where(f => keesSet.Contains(f.Key));
      

      但是对于这么大的集合,它仍然需要相当长的时间来执行搜索。

    【讨论】:

    • "list" of foos 在这个阶段没有具体化,所以希望(可能是错误的) Contains() 将执行数据库的查询。将使键成为哈希集并测试...
    • 要使数据库查询foos 必须是IQueryable&lt;Entity&gt;,而不是IEnumerable&lt;Entity&gt;。然后使用Contains 将在SQL 查询中生成正确的IN () 语句。
    • 会确保它是 IQueryable - HashSet 对于 Contains() 会更好吗?
    • 当您使用IQueryable 时并不重要。 IEnumerable&lt;string&gt; 就可以了。
    【解决方案2】:

    我认为还有一个类似 join clause 的变体

    IEnumerable<Foo> foos
    IEnumerable<string> fooKeys
    
    var matchedFoos = from foo in foos
                      join fk in fooKeys on foo.Key equals fk
                      select foo;
    

    【讨论】:

      猜你喜欢
      • 2021-04-17
      • 1970-01-01
      • 1970-01-01
      • 2011-05-06
      • 2014-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-04
      相关资源
      最近更新 更多