如何使用 LINQ 避免在 Where() 子句中调用 Contains()?

Dav*_*bin 0 c# linq

我有一个非常简单的 LINQ 表达式:

class Foo
{
   ...
   int Id { get; }
}

IEnumerable<Foo> foos = ...;
IEnumerable<int> ids = ...;

var remainder = foos.Where(f => !ids.Contains(f.Id));
Run Code Online (Sandbox Code Playgroud)

我认为可能有一种方法可以remainder使用Join()and/orIntersection()和/or生成相同的集合Except(),但我不够聪明,无法制定它。

!在 Join() 中苦苦挣扎,因为就以下方面而言,投影集交集Join()是:

var intersection = foos.Join(ids, f => f.Id, i => i, (f, id) => f);
Run Code Online (Sandbox Code Playgroud)

但我正在寻找相反的东西。你能帮我吗?谢谢!

Iva*_*oev 5

您在关系代数中寻求的是Antijoin。在关系数据库中它通常是与实现left outer join(或左边的半连接,如果我们使用相同的术语)与检查rightNULL。最接近的 LINQ 构造是GroupJoin,它检查空的内部组。

这是它将如何查找您的示例(将其与Contains基于版本进行比较)

查询语法:

var remainder = from foo in foos
        join id in ids on foo.Id equals id into idGroup
        where !idGroup.Any()
        select foo;
Run Code Online (Sandbox Code Playgroud)

方法语法:

var remainder = foos.GroupJoin(ids, foo => foo.Id, id => id, (foo, idGroup) => new { foo, idGroup })
    .Where(e => !e.idGroup.Any())
    .Select(e => e.foo);
Run Code Online (Sandbox Code Playgroud)