[C#] 你如何做一个“不在”查询与LINQ?


Answers

你想要Except运算符。

var answer = list1.Except(list2);

这里更好的解释: http://blogs.msdn.com/charlie/archive/2008/07/12/the-linq-set-operators.aspx : http://blogs.msdn.com/charlie/archive/2008/07/12/the-linq-set-operators.aspx

注:此技术仅适用于基元类型,因为您必须实施IEqualityComparer才能将Except方法用于复杂类型。

Question

我有两个集合在两个集合中都有属性Email 。 我需要获得第一个列表中Email不存在于第二个列表中的项目列表。 使用SQL我只是使用“不在”,但我不知道在LINQ中的等价物。 这是如何完成的?

到目前为止,我有一个加入,如...

var matches = from item1 in list1
join item2 in list2 on item1.Email equals item2.Email
select new { Email = list1.Email };

但我不能加入,因为我需要差异,加入会失败。 我需要一些使用Contains或Exists的方式,我相信。 我还没有找到一个例子来做到这一点。




难道你不能做一个外部连接,只有在该组为空时才从第一个列表中选择项目? 就像是:

Dim result = (From a In list1
              Group Join b In list2 
                  On a.Value Equals b.Value 
                  Into grp = Group
              Where Not grp.Any
              Select a)

我不确定这是否会以Entity框架的任何有效方式工作。




谢谢,布雷特。 你的建议也帮助了我。 我有一个对象列表,并希望使用另一个对象列表来过滤它。 再次感谢....

如果有人需要,请查看我的代码示例:

'First, get all the items present in the local branch database
Dim _AllItems As List(Of LocalItem) = getAllItemsAtBranch(BranchId, RecordState.All)

'Then get the Item Mappings Present for the branch
Dim _adpt As New gItem_BranchesTableAdapter
Dim dt As New ds_CA_HO.gItem_BranchesDataTable
    _adpt.FillBranchMappings(dt, BranchId)

Dim _MappedItems As List(Of LocalItem) = (From _item As LocalItem In _AllItems Join _
    dr As ds_CA_HO.gItem_BranchesRow In dt _
    On _item.Id Equals dr.numItemID _
    Select _item).ToList

_AllItems = _AllItems.Except(_MappedItems.AsEnumerable).ToList

 Return _AllItems



var secondEmails = (from item in list2
                    select new { Email = item.Email }
                   ).ToList();

var matches = from item in list1
              where !secondEmails.Contains(item.Email)
              select new {Email = item.Email};



对于从一组内存对象开始并针对数据库查询的人,我发现这是最好的方法:

var itemIds = inMemoryList.Select(x => x.Id).ToArray();
var otherObjects = context.ItemList.Where(x => !itemIds.Contains(x.Id));

这在SQL中产生了一个很好的WHERE ... IN (...)子句。




为简单起见使用int列表的示例。

List<int> list1 = new List<int>();
// fill data
List<int> list2 = new List<int>();
// fill data

var results = from i in list1
              where !list2.Contains(i)
              select i;

foreach (var result in results)
    Console.WriteLine(result.ToString());



您可以将这两个集合放在两个不同的列表中,比如list1和list2。

然后,只写

list1.RemoveAll(Item => list2.Contains(Item));

这将工作。