c# - Linq 性能 : Any vs. 包含

标签 c# performance linq

<分区>

这个问题与this one有关,但我认为不完全相同。

给定:

class Foo
{
  public string Bar { get; set; }
}
...
var c1 = new List<Foo>() { ... };
var c2 = new List<Foo>() { ... };

以下 2 个循环给出相同的结果:

  foreach (var item in c2.Where(f => c1.Any(f1 => f1.Bar.Equals(f.Bar))))
  { ... }

  foreach (var item in c2.Where(f => c1.Select(f1 => f1.Bar).Contains(f.Bar)))
  { ... }

它们的速度一样快吗?

the other question的区别, 是这里额外的Select 语句是否改变了底层集合性质的重要性。

换句话说:这是否包含:

foos.Contains(foo1)

按照与此相同的 “集合类型” 操作:

foos.Select(f=>f.Bar).Contains(foo1.Bar)

我可能 - 天真的 - 想法可能是:“一旦我们落后于 Linq 的 Select,一切都只是‘列表’,所以 Any 和 Contains 都是 O(n)。”

最佳答案

这两个查询从根本上实现了相同的算法。它们将为 c2 中的每个项目分别迭代 c1,比较两个对象的 Bar 属性,并在找到匹配项后立即返回.这两种情况的渐近复杂性是相同的,这意味着随着这两个集合的大小增加,它们的扩展性同样好(或同样糟糕,视情况而定)。

两者在与一种方法相关的开销方面可能存在微小差异,但差异不会很大,并且随着集合大小的增加它们会越来越小。没有任何真正的性能理由来选择两者之一。

有一个您没有展示的选项比其中任何一个都快得多。您可以使用 Join 查找 c1 中也存在于 c2 中的所有项目,而无需对序列进行线性搜索:

var query = from first in c1
    join second in c2
    on first.Bar equals second.Bar
    select first;

另一种选择是使用 HashSet 而不是 List,因为这样更容易搜索:

var set = new HashSet<string>(c1.Select(item => item.Bar));

var query = c2.Where(item => set.Contains(item.Bar));

(这个解决方案非常接近 Join 将在内部执行的操作。)

这两种解决方案都比您提出的任何一种解决方案都快很多

关于c# - Linq 性能 : Any vs. 包含,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17302096/

相关文章:

c# - LINQ GroupBy 返回列表作为结果

c# - 将 XML 转换为动态 C# 对象

c# - 检查字符串的格式

Android Hierarchy Viewer 无法在设备模拟器上加载窗口数据。字符串索引超出范围 173

python - 在 python 中获取子字符串的更快方法?

c# - 多嵌套 FirstOrDefault

c# - 难以理解特定的 lambda 表达式

c# - Azure SQL 数据库列表 - 服务器使用 REST API 的使用情况

c# - UWP 窗口内容不随窗口调整大小

performance - Matlab:如何对二维向量集上的嵌套循环进行向量化