使用 LINQ 过滤列表

Posted

技术标签:

【中文标题】使用 LINQ 过滤列表【英文标题】:Filter lists with LINQ 【发布时间】:2022-01-12 12:20:36 【问题描述】:

我有,列出StudentsTeachers

var students = new List<Student>
    
        new Student
        
            Id= 1,
            Name = "AA",
            City = "London",
            Country = "UK"
        ,
        new Student
        
            Id= 2,
            Name = "BB",
            City = "New Orleans",
            Country = "USA"
        
    

var teachers = new List<Teacher>
    
        new Teacher
        
            Id = 1,
            Name = "CC",
            City = "Berlin",
            Country = "Germany"
        ,
        new Teacher
        
            Id = 2,
            Name = "DD",
            City = "Mexico D.F.",
            Country = "Mexico"
        
    

我想为每位教师获得一份位于同一国家和同一城市的学生名单。

到目前为止我做了什么:

var result = from teacher in teachers
                     select new
                     
                         teacher,
                         Students = students.Where(s => s.Country == teacher.Country && s.City == teacher.City).ToList()
                     ;

这不起作用,我得到了casting exception。并尝试:

var result = new List<(Teacher, IEnumerable<Student>)>();

teachers.ToList().ForEach(c => result.Add((c,
        students.Where(s => s.Country == c.Country && s.City == c.City).ToList())));

这很好,但是,有没有其他方法,没有循环?

【问题讨论】:

是的,这对于 LINQ 来说是非常可行的。 foreach 不是必需的。使用SelectWhere 的组合,您可以获得您想要的结果。 var teachersWithStudents = teachers.Select(teacher =&gt; new teacher, Students = students.Where(s =&gt; s.Country == teacher.Country &amp;&amp; s.City == teacher.City).ToList() ).ToList() 澄清一下,linq 也是一个 foreach,当你执行 ToList 时,你循环抛出所有列表相同 :) 但是是的 @nbokmans 解决方案应该可以工作 @nbokmans 得到了System.InvalidCastException : Unable to cast object of type System.Collections.Generic.List1[&lt;&gt;f__AnonymousType02[Teacher, System.Collections.Generic.List1[Student]]] to type System.Collections.Generic.IEnumerable1[System.ValueTuple2[Teacher,System.Collections.Generic.IEnumerable1[Student]]]'. @Alen.Toma 我相信@nbokmans 在 OP 的问题中引用了 .Tolist().ForEach(...)。说到:ForEach(...)List&lt;T&gt;的void方法,实际上是foreach (x in y) 的语法糖,与LINQ无关 【参考方案1】:

您的 linq 查询是正确的。您的查询返回匿名类型的列表。您不能将其直接转换为元组列表。 您遇到的问题是您尝试转换为哪种类型。如果你想得到像 IEnumerable 这样的元组列表的结果,你应该编写如下代码:

        var result = from teacher in teachers
                     select (
                         teacher,
                         students.Where(s => s.Country == teacher.Country && s.City == teacher.City).ToList()
                         );

那么, result.ToList() 会给你一个元组列表, result.ToArray() 会给你一个元组数组

Lambda 表达式替代:

var result = teachers
            .Select(teacher => (teacher, students.Where(s => s.Country == teacher.Country && s.City == teacher.City).ToList()));

但是,我更喜欢匿名列表作为返回类型而不是元组。

【讨论】:

以上是关于使用 LINQ 过滤列表的主要内容,如果未能解决你的问题,请参考以下文章

使用 linq 过滤繁琐的对象列表

使用 LINQ 过滤列表

CSharp使用另一个列表及其嵌套列表过滤带有LINQ查询的列表

使用列表属性通过 LINQ 过滤 dbset

使用 Linq 根据条件过滤对象列表

可以使用 DateTime 列表过滤 List<object> 的 Linq 查询