【问题标题】:Speed improvement in LINQ Where(Array.Contains)LINQ Where(Array.Contains) 中的速度改进
【发布时间】:2013-10-14 11:24:59
【问题描述】:

我最初有一个包含返回 int[] 的 LINQ 查询的方法,后来以类似于以下方式使用它:

int[] result = something.Where(s => previousarray.Contains(s.field));

事实证明这非常慢,直到第一个数组被检索为本机IQueryable<int>。它现在运行得非常快,但我想知道如果我从其他地方获得了 int[],然后必须像上面那样使用它,我将如何处理这种情况。

有没有办法在这种情况下加快查询速度?转换为列表似乎没有帮助。

【问题讨论】:

标签: c# arrays linq


【解决方案1】:

在 LINQ-SQL 中,Contains 将转换为 SELECT ... WHERE field IN(...),并且应该相对较快。然而,在 LINQ-Objects 中,如果源是 ICollection<T>,它将调用 ICollection<T>.Contains。

当 LINQ-SQL 结果被视为 IEnumerable 而不是 IQueryable 时,您将丢失 linq 提供程序 - 即,任何进一步的操作都将在内存中而不是在数据库中完成。

至于为什么它的内存慢很多:

Array.Contains() 是一个 O(n) 操作,所以

something.Where(s => previousarray.Contains(s.field));

是 O(p * s),其中 p 是 previousarray 的大小,s 是 something 的大小。

HashSet<T>.Contains() 另一方面是一个 O(1) 操作。如果您首先创建一个哈希集,您会看到 .Contains 操作有很大的改进,因为它将是 O(s) 而不是 O(p * s)。

例子:

var previousSet = new HashSet<int>(previousarray);
var result = something.Where(s => previousSet.Contains(s.field));

【讨论】:

  • 先生的精彩解释!
【解决方案2】:

Where 对 Lists/Arrays/IEnumarables 等是 O[N] 操作。在 HashSet 上是 O[~1]。所以你应该尝试使用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-08
    • 1970-01-01
    • 2020-05-29
    • 1970-01-01
    • 2013-05-04
    • 2016-05-30
    • 2011-01-16
    相关资源
    最近更新 更多