简体   繁体   English

C# - Linq有两个列表

[英]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 . 使用JoinWhere 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM