[英]C# - Linq with two Lists
I've got 2 classes which are connected together via an ID: 我有两个通过ID连接在一起的课程:
public class A {
public int AID;
public string Name;
}
public class B {
public int BID;
public int AID;
}
Now I want to filter my listB to get all B where A 's Name is euqals the parameter name : 现在我想过滤我的listB以获取所有B ,其中A的名称是euqals参数名称 :
List<A> listA = ...;
List<B> listB = ...;
public List<B> Filter(string name) {
var list = listB.Where(**... A.Name == name ...**).ToList();
return list;
}
I don't know how to filter listB with the parameter I defined above. 我不知道如何使用上面定义的参数过滤listB。 Maybe someone can help me figuring it out.
也许有人可以帮我搞清楚。
Thanks! 谢谢!
Use Join
and Where
. 使用
Join
和Where
。 I prefer the query syntax with joins: 我更喜欢使用连接的查询语法:
IEnumerable<B> bs =
from a in listA
join b in listB on a.AID equals b.AID
where a.Name == name
select b;
List<B> list = bs.ToList();
Another way which avoids duplicate B's (if it's a 1-to-many relationship) is using a lookup: 避免重复B的另一种方法(如果它是1对多的关系)是使用查找:
ILookup<int, string> aNameLookup = listA.ToLookup(a => a.AID, a => a.Name);
List<B> list = listB.Where(b => aNameLookup[b.AID].Contains(name)).ToList();
Although you could filter a list of B
s using b.AID
linear search, it would be inefficient: 虽然您可以使用
b.AID
线性搜索过滤B
列表,但效率很低:
return listB.Where(b => listA.FirstOrDefault(a => a.AID == b.AID)?.Name == name);
A better approach would be to place entries from listA
into a Dictionary<int,A>
, and use dictionary lookup by b.AID
: 更好的方法是将
listA
条目放入Dictionary<int,A>
,并使用b.AID
字典查找:
IDictionary<int,A> dictA = listA.ToDictionary(a => a.AID);
return listB.Where(b => dictA.TryGetValue(b.AID, out var a) && a.Name == name);
I would highly recommend keeping A
s in dictA
rather than listA
, because it would let you avoid rebuilding the dictionary for each query. 我强烈建议将
A
s保存在dictA
而不是listA
,因为它可以让你避免为每个查询重建字典。
try join like as below in linq 尝试如下所示加入linq
form b in listB
join a in listA.Where(A.Name == name)
on a.AID equals b.AID
select b;
or get list of id first and then filter out 或先获取id列表然后过滤掉
var ids = from a in listA
where A.Name == name
select a.AID;
var Bs = from b in listB
where ids.Contain(b.AID)
select b;
use group join to avoid introducing duplication in listB. 使用组连接以避免在listB中引入重复。
var filteredA = listA.Where(a => a.Name == name);
var query =
from b in listB
join a in filteredA on b.AID equals a.AID into matchedAgroup
where matchedAgroup.Any()
select b;
I have used this in the past for a succinct subset list: 我过去曾使用过这个简洁的子集列表:
public void TestGetListBMatchingListA()
{
List<ClassA> listClassA = new List<ClassA>();
listClassA.Add(new ClassA { ClassAId = 1, Name = "JayV1" });
listClassA.Add(new ClassA { ClassAId = 2, Name = "JayV2" });
listClassA.Add(new ClassA { ClassAId = 3, Name = "JayV3" });
listClassA.Add(new ClassA { ClassAId = 4, Name = "JayV4" });
listClassA.Add(new ClassA { ClassAId = 5, Name = "JayV5" });
List<ClassB> listClassB = new List<ClassB>();
listClassB.Add(new ClassB { ClassBId = 1, ClassAId = 1 });
listClassB.Add(new ClassB { ClassBId = 2, ClassAId = 2 });
listClassB.Add(new ClassB { ClassBId = 3, ClassAId = 3 });
listClassB.Add(new ClassB { ClassBId = 4, ClassAId = 4 });
listClassB.Add(new ClassB { ClassBId = 5, ClassAId = 1 });
listClassB.Add(new ClassB { ClassBId = 6, ClassAId = 2 });
listClassB.Add(new ClassB { ClassBId = 7, ClassAId = 3 });
listClassB.Add(new ClassB { ClassBId = 8, ClassAId = 4 });
listClassB.Add(new ClassB { ClassBId = 9, ClassAId = 5 });
listClassB.Add(new ClassB { ClassBId = 10, ClassAId = 1 });
var result = listClassB.Where(classB =>
listClassA.Any(classA =>
classB.ClassAId == classA.ClassAId
&& classA.Name == "JayV1")).ToList();
result.ForEach(r => Debug.WriteLine(r.ClassBId));
}
It produces the result of: 它产生的结果是:
1
5
10
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.