LINQ 查询,用于在与泛型列表不同的列表之间进行选择
本文关键字:列表 之间 选择 行选 LINQ 用于 泛型 查询 | 更新日期: 2023-09-27 17:50:13
我有两个通用列表,我想在其中运行几个 Linq 查询来找出:
-
列表 A 中的任何项目是否在列表 B 中找到
-
列表 A 中的所有项目都在列表 B 中找到吗
以下是列表:
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. 列表 A 中的所有多头都可以在列表 B 中找到吗?
列表 A 和列表 B 可以是不同的长度。 对于数字 2,我需要在 ListB 中找到的所有 ListA 项目,反之亦然。 我希望这是有道理的。
谢谢
-斯科特
首先,你只关心 ListB 中的 ItemId,所以:
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的子集。
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 是 B 的子集时,A.Except(B).Any()
给出 false,因为结果中没有元素;因此,如果我们想处理这种情况,我们显然会否定它。
为了完整起见,如果我们交换 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 对集合差或相对集合补码的名称。维基教科书对集合论有一个不错的介绍,如果你有这样的倾向。
var value1 =
(
from itemA in ListA
where ListB.Any(itemB => itemB.ItemID == itemA)
select item
).Count();
var value2 = value1 == ListA.Count();
为了测试条件,假设您将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));
如果需要同时回答所有三个问题,则纯 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;