如何使用LINQ避免在Where()子句中调用Contains()? [英] How can I use LINQ to avoid calling Contains() inside a Where() clause?

查看:274
本文介绍了如何使用LINQ避免在Where()子句中调用Contains()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

var remainder = foos.Where(f => !ids.Contains(f.Id));

我在想可能有一种方法可以使用Join()和/或Intersection()和/或Except()来产生相同的remainder集合,但是我不够聪明来表述它. /p>

我正在Join()中为!苦苦挣扎,因为根据Join()的投影集 intersection 是:

var intersection = foos.Join(ids, f => f.Id, i => i, (f, id) => f);

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

解决方案

您在 GroupJoin ,并检查内部的空组.

以下是查找示例的方法(将其与基于Contains的版本进行比较)

查询语法:

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

方法语法:

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

I've got a LINQ expression that's pretty straightforward:

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

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

var remainder = foos.Where(f => !ids.Contains(f.Id));

I'm thinking that there might be a way to produce the same remainder set using Join() and/or Intersection() and/or Except(), but I'm not clever enough to formulate it.

I'm struggling with the ! in the Join(), because projected-set intersection in terms of Join() is:

var intersection = foos.Join(ids, f => f.Id, i => i, (f, id) => f);

but I'm looking for the inverse. Can you help? Thanks!

解决方案

What you are seeking for in the Relational algrebra is called Antijoin. In relational database it's implemented usually with left outer join (or left semijoin if we use the same terminology) with checking right side for NULL. The closest LINQ construct is the GroupJoin with check for empty inner group.

Here is how it will look for your sample (compare it to Contains based version)

Query syntax:

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

Method syntax:

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

这篇关于如何使用LINQ避免在Where()子句中调用Contains()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆