[英]LINQ Query: Determining if object in one list exists in another based on key
Basically what I'm trying to do is take a list of objects and filter it based on a number of criteria where one of the criteria is that the key doesn't exist in another list. 基本上我要做的是获取一个对象列表并根据一些标准对其进行过滤,其中一个标准是该键在另一个列表中不存在。 Here's an example:
这是一个例子:
My two classes are similar to this: 我的两个类与此类似:
public class Test
{
public string name;
public string instructor_name;
public string course;
}
public class Appointment
{
public string site;
public DateTime forWhen;
public string testName;
}
I want to sort through a List<Test> by looking at the course and making sure that test doesn't exist in the List<Appointment>. 我想通过查看课程并确保List <Appointment>中不存在测试来对List <Test>进行排序。 In SQL I'd do it something like this:
在SQL中我会这样做:
SELECT new Group<Test>(c.Key, c)
FROM tests in testList
WHERE tests.Course != "Science"
AND tests.name NOT IN (SELECT testName FROM appotList)
However, I can't figure out how I would do this in LINQ. 但是,我无法弄清楚如何在LINQ中执行此操作。 Any ideas?
有任何想法吗?
If you're talking about performing client-side filtering, that's pretty easy with LINQ to Objects. 如果您正在谈论执行客户端过滤,那么使用LINQ to Objects非常容易。 Something like this:
像这样的东西:
List<Test> tests = ...;
List<Appointment> appts = ...;
var query = tests.Except(
tests.Join(appts, t => t.name, a => a.testName, (t, a) => t));
The following is slightly simpler to read: 以下内容略微简单易读:
var query = tests.Where(t => !appts.Any(a => a.testName == t.name));
But the first version will be faster, since the Join
function will compute a hash table of the matches rather than doing a linear search of the appts
list for every element in tests
. 但是第一个版本会更快,因为
Join
函数将计算匹配的哈希表,而不是对tests
每个元素进行appts
列表的线性搜索。
http://introducinglinq.com/blogs/marcorusso/archive/2008/01/14/the-not-in-clause-in-linq-to-sql.aspx http://introducinglinq.com/blogs/marcorusso/archive/2008/01/14/the-not-in-clause-in-linq-to-sql.aspx
Consider this code that returns all the customers who don't have an order in the Orders table. 请考虑此代码,该代码返回Orders表中没有订单的所有客户。 This is one SQL query that returns that value.
这是一个返回该值的SQL查询。
SELECT *
FROM [dbo].[Customers] AS [t0]
WHERE [t0].[CustomerID] NOT IN (
SELECT [t1].[CustomerID]
FROM [dbo].[Orders] AS [t1]
)
This is not the faster way to get the desired result (using a NOT EXISTS is the favorite way - more on this shortly). 这不是获得所需结果的更快方式(使用NOT EXISTS是最喜欢的方式 - 更多关于这一点)。 LINQ offers a Contains extension method that allows writing the following code.
LINQ提供了一个包含扩展方法,允许编写以下代码。
NorthwindDataContext dc = new NorthwindDataContext();
dc.Log = Console.Out;
var query =
from c in dc.Customers
where !(from o in dc.Orders
select o.CustomerID)
.Contains(c.CustomerID)
select c;
foreach (var c in query) Console.WriteLine( c );
In LINQ to SQL the query is translated into this SQL code: 在LINQ to SQL中,查询被转换为此SQL代码:
SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName],
[t0].[ContactTitle], [t0].[Address], [t0].[City],
[t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0]
WHERE NOT (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[Orders] AS [t1]
WHERE [t1].[CustomerID] = [t0].[CustomerID]
))
This approach is not only semantically equivalent, but also faster in execution. 这种方法不仅在语义上等同,而且执行速度更快。 The following is the result with SET STATISTICS IO ON.
以下是SET STATISTICS IO ON的结果。 The first result is for the hand-written query that use the NOT IN clause.
第一个结果是使用NOT IN子句的手写查询。 The second result is for the LINQ to SQL generated query.
第二个结果是LINQ to SQL生成的查询。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.