linq 连接中是不是存在“不等于”

Posted

技术标签:

【中文标题】linq 连接中是不是存在“不等于”【英文标题】:Is there a "not equal" in a linq joinlinq 连接中是否存在“不等于” 【发布时间】:2011-04-15 08:10:40 【问题描述】:

我正在尝试完成下面的 LINQ 查询,但我需要一个“不等于”而不是等于,以便过滤员工拥有来自 groupA 减去 groupB 的所有员工。

List<Employee> groupA = getEmployeeA();
List<Employee> groupB = getEmployeeB();        

var filteredEmployees = from a in groupA 
                        join b in groupB on a.Name equals b.Name
                        select a;

【问题讨论】:

Using Linq not equals的可能重复 【参考方案1】:

您不需要加入:

var filteredEmployees = groupA.Except(groupB);

请注意,这将是一系列独特的员工 - 因此,如果 groupA 中有任何重复项,它们只会在 filteredEmployees 中出现一次。当然,它还假设您有一个合理的相等比较器1。如果需要专门去名字,可以使用ExceptBy from MoreLINQ:

var filteredEmployees = groupA.ExceptBy(groupB, employee => employee.Name);

或者不进入第三方库:

var groupBNames = new HashSet<string>(groupB.Select(x => x.Name));
var filteredEmployees = groupA.Where(x => !groupBNames.Contains(x.Name));

1 正如 cmets 中所指出的,您可以将 IEqualityComparer&lt;T&gt; 作为参数传递给 Except。我在MiscUtil 中有一个ProjectionEqualityComparer 类,可以轻松构建您需要的比较器:

// I can't remember the exact method name, but it's like this :)
var comparer = ProjectionEqualityComparer<Employee>.Create(x => x.Name);
var filteredEmployees = groupA.Except(groupB, comparer);

【讨论】:

@Robert 请注意:您可以为Except 的重载提供IEqualityComparer&lt;Employee&gt; 实现。如果覆盖 Equals/GetHashCode (a) 不可能或 (b) 不可取,则很有用。 谢谢。你写的第三个选项成功了。我之前尝试过 IEqualityComparer,但它不起作用。 我喜欢没有第 3 方的 hashset 方法。这很漂亮。 可能需要加入说我有两个表员工和部门,我想通过部门的主键将员工与部门联系起来,但是部门和员工都有列费用,我希望员工费用不等于部门费用的结果(AND 操作) @VISHMAY:这远远超出了 OP 的要求。【参考方案2】:

不,“不等于”运算符将为您提供 groupA 和 groupB 的所有组合,但项目相同的组合除外。

使用 except 方法可以得到你想要的:

var filteredEmployees = groupA.Except(groupB);

【讨论】:

【参考方案3】:

在 Entity Framework 6 中,我使用

获得了更好的结果
var filteredEmployees = groupA.Where(a => !groupB.Select(b => b.Name).Contains(a.Name));

【讨论】:

以上是关于linq 连接中是不是存在“不等于”的主要内容,如果未能解决你的问题,请参考以下文章

LINQ 是不是使用 DataRelations 来优化连接?

何时更喜欢用 SelectMany() 表示的连接而不是用 Linq 中的 join 关键字表示的连接

在 Entity Framework Core 中,如何使用数据库级别的条件(不是本地 LINQ)查询连接表上的数据?

Linq to SQL 左外连接不是

当其中一种数据类型可以为空而另一种不能为空时,是不是可以使用 linq 进行匿名连接? [复制]

Linq中的lambda /方法语法中的左外连接[重复]