LINQ查询选择与通用列表不同

时间:2011-04-13 22:30:24

标签: c# linq

我有两个通用列表,我想运行几个Linq查询来查找:

  1. 列表B中的任何列表A项目

  2. 列表B中的所有列表A项目

  3. 以下是清单:

    var ListA = new List<long>()
    var ListB = new List<MyObject>()
    

    MyObject定义为:

    public class MyObject
      {
        public long ItemId { get; set; }    
        // ... Other stuff...
      }
    

    我正在尝试确定两件事(两个查询):1。ListA中的任何长整数是否与ListB中的任何MyObject.ItemId匹配? 2. ListA中的所有多头都可以在ListB中找到吗?

    ListA和ListB的长度可以不同。对于2号,我需要在ListB中找到所有ListA的项目,但反之亦然。我希望这是有道理的。

    谢谢,

    -Scott

4 个答案:

答案 0 :(得分:6)

首先,你只关心ListB中的ItemIds,所以:

var bIDs = ListB.Select(x => x.ItemId);

要回答问题的第一部分,我会通过找到两个列表的交集(它们共享的所有项目的集合)来解决这个问题。如果它中至少有一个元素,则两者之间存在重叠。

var sharedIds = ListA.Intersect(bIDs);
if (sharedIds.Any())
    // list A contains at least one ItemID which ListB contains

至于第二部分,你想看看列表A是否是列表B的子集。搜索这个,Stack Overflow呈现clean solution

if (!ListA.Except(bIDs).Any())
    // yes, list A is a subset of list B

此代码段有效,因为ListA.Except(bIDs)找到了ListA所拥有的bIDs没有的元素。如果这是空的,则ListA不包含bIDs没有的任何内容。因此,ListA中的所有内容也位于bIDs

以下是一个例子:A = {1, 2}; B = {1, 2, 3}。 A是B的一个子集。A.Except(B)给你一个空集 - B有1和2,所以不能在结果列表中,并且B中没有任何东西。所以当A是a时B的子集,A.Except(B).Any()给出错误,因为结果中没有元素;所以如果我们想处理那个案子,我们显然会否定它。

为了完整性,如果我们交换A和B轮,使得A不是B的一个子集:A = {1, 2, 3}; B = {1, 2},然后A.Except(B)提供{3}。它不能包含1或2,因为B包含1和2.但是B不包含3,因此A.Except(B) 可以包含它。由于{3}包含一个元素,因此它不为空,因此A.Except(B).Any()为真。否定,如果A不是B的子集,则为假。

我的解释有点简洁;如果你想进一步研究(我建议你这样做 - 一点设定理论可以走很长的路),A.Except(B)是LINQ的集合差异或相对集合补充的名称。如果你这么倾向的话,Wikibooks有一套很好的introduction来设定理论。

答案 1 :(得分:1)

var value1 =
(
    from itemA in ListA
    where ListB.Any(itemB => itemB.ItemID == itemA)
    select item
).Count();

var value2 = value1 == ListA.Count();

答案 2 :(得分:0)

要测试条件,假设您将ItemIds列表提取到listB

bool inListA = listA.Any(x => listB.Contains(x));

bool allInListB = listA.All(x => listB.Contains(x));

如果ItemIds

,则在不提取单独列表的情况下进行测试
bool inListA = listA.Any(x => listB.Select(b => b.ItemId).Contains(x));

bool allInListB = listA.All(x => listB.Select(b => b.ItemId).Contains(x));

答案 3 :(得分:0)

如果您需要同时回答所有三个问题,那么纯LINQ解决方案很可能不是最优的,因为每个查询都需要执行相同的交叉操作。交叉一次,然后使用该结果回答你的三个问题:

var tempSet = new HashSet<long>(ListA);
int uniqueAItemCount = tempSet.Count;

// 2b. "I would need all of ListA's items found in ListB, but not vice-versa."
tempSet.IntersectWith(ListB.Select(x => x.ItemId));
// tempSet now contains all items from ListA also found in ListB
// we can use this result to answer the other two questions...

// 1. "Do any of the longs in ListA match any of the MyObject.ItemId in ListB?"
bool anyAFoundInB = tempSet.Count > 0;

// 2a. "Can all of the longs in ListA be found in ListB?"
bool allAFoundInB = tempSet.Count == uniqueAItemCount;