使用LINQ到对象找到一个集合的项目不匹配的另一
我想找到一个集合中的所有项目不匹配的另一个集合。的集合是不同类型的,虽然,我想写一个lambda表达式来指定平等。
I want to find all items in one collection that do not match another collection. The collections are not of the same type, though; I want to write a lambda expression to specify equality.
一个 LINQPad 例子什么我想要做的:
A LINQPad example of what I'm trying to do:
void Main()
{
var employees = new[]
{
new Employee { Id = 20, Name = "Bob" },
new Employee { Id = 10, Name = "Bill" },
new Employee { Id = 30, Name = "Frank" }
};
var managers = new[]
{
new Manager { EmployeeId = 20 },
new Manager { EmployeeId = 30 }
};
var nonManagers =
from employee in employees
where !(managers.Any(x => x.EmployeeId == employee.Id))
select employee;
nonManagers.Dump();
// Based on cdonner's answer:
var nonManagers2 =
from employee in employees
join manager in managers
on employee.Id equals manager.EmployeeId
into tempManagers
from manager in tempManagers.DefaultIfEmpty()
where manager == null
select employee;
nonManagers2.Dump();
// Based on Richard Hein's answer:
var nonManagers3 =
employees.Except(
from employee in employees
join manager in managers
on employee.Id equals manager.EmployeeId
select employee);
nonManagers3.Dump();
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Manager
{
public int EmployeeId { get; set; }
}
以上的作品,并将返回员工比尔(#10)。它似乎并不优雅,虽然,这可能是低效率的较大集合。在SQL中我可能会做一个LEFT JOIN和查找项目,其中第二ID为NULL。什么是对LINQ这样做的最佳做法
The above works, and will return Employee Bill (#10). It does not seem elegant, though, and it may be inefficient with larger collections. In SQL I'd probably do a LEFT JOIN and find items where the second ID was NULL. What's the best practice for doing this in LINQ?
编辑:?更新以防止取决于标识等于指数的解决方案
Updated to prevent solutions that depend on the Id equaling the index.
编辑:添加cdonner的解决方案 - 任何人有什么简单
Added cdonner's solution - anybody have anything simpler?
编辑:添加一个变种理查德海恩的回答,我目前最喜欢的? !感谢大家的一些优秀的答案
Added a variant on Richard Hein's answer, my current favorite. Thanks to everyone for some excellent answers!
这是几乎一样的,有些其他的例子却少代码:
This is almost the same as some other examples but less code:
employees.Except(employees.Join(managers, e => e.Id, m => m.EmployeeId, (e, m) => e));
这不是任何简单得多employees.Where(E =>!managers.Any(M =>米.EmployeeId == e.Id))或原始语法,但是。
It's not any simpler than employees.Where(e => !managers.Any(m => m.EmployeeId == e.Id)) or your original syntax, however.