【问题标题】:Linq lambda for searching a List within a List, finding a match, then deleting it from the listLinq lambda 用于在列表中搜索列表,找到匹配项,然后将其从列表中删除
【发布时间】:2011-06-16 16:26:39
【问题描述】:

我正在尝试学习 Linq,我需要有关在列表中搜索列表、找到匹配项并将其删除的方法的帮助。例如,假设我有一个名为 Student 的类:

public class Student
{
   string FirstName;
   string LastName;
}

然后想象我有另一个名为Classroom 的类,它有一个List<Student>

public class Classroom
{
   List<Student> Students;
}

最后,我还有一个类,叫做School,它有一个Classrooms的列表:

public class School
{
   List<Classroom> Classrooms;
}

然后,我需要一个接收Student 对象的方法,检查学生是否在学校,如果在,则将其删除。如果他们在学校,该方法应该删除他们并返回 true。如果他们不在学校,该方法应该返回 false 并且不采取任何行动。这是一个使用 foreach 循环的示例,我想摆脱它:

public bool RemoveStudentFromSchool(Student student)
{
   foreach (Classroom c in Classrooms)
   {
      foreach (Student s in c.Students)
      {
         if ((student.FirstName == s.FirstName) && (student.LastName == s.LastName))
         {
            s.Remove(student);

            return true;
         }
      }
   }

   return false;
}

【问题讨论】:

    标签: c# linq lambda


    【解决方案1】:

    这假设一个学生只能在一个房间里,Student 的名字和姓氏是 IEquatable(或引用相同):

    var roomWithStudent = Classrooms.FirstOrDefault(c => c.Students.Any(s => s.Equals(student));
    if (roomWithStudent != null)
    {
        roomWithStudent.Remove(student);
        return true;
    }
    return false;
    

    如果Student 不是IEquatable 并且传入的搜索对象不一定是相同的引用,则另一种方法:

    var roomWithStudent = Classrooms
                            .SelectMany(c => c.Students.Select(s => new { Room = c, Student = s }))
                            .Where(rs => (student.FirstName == rs.Student.FirstName) && (student.LastName == rs.Student.LastName))
                            .FirstOrDefault();
    
    if (roomWithStudent != null)
    {
        roomWithStudent.Room.Students.Remove(roomWithStudent.Student);
        return true;
    }
    return false;
    

    【讨论】:

    • 应该是:Any(s => (student.FirstName == s.FirstName && student.LastName == s.LastName))
    • @ub1k:不知道你到底是什么意思——你能详细说明一下吗?
    • @ub1k chris 提到第一种方法是使用 IEquatable,这意味着他应该自己实现 equals 和 gethashcode
    • 根据我的经验,lambda 表达式中的整个逻辑语句必须放在一个括号中。自己检查一下。我相信这是一个编译器问题。
    • @ub1k:我不这么认为。在 VS2010 中这样对我来说很好
    【解决方案2】:

    扩展方法怎么样..

    public static bool RemoveFromRoom(this Student student,School school)
    {
        if (student == null) throw new ArgumentNullException("student");
        if (school == null) throw new ArgumentNullException("school");
        bool ret = false;
        var room = school.Classrooms.SingleOrDefault(cr=>cr.Students.Contains(student));
        if (room !=null)
        {
            ret = true;
            room.Students.Remove(student);
        }
    
        return ret;
    }
    

    用法

    student.RemoveFromRoom(instanceOfSchool);
    

    或者……

    public static bool RemoveStudentFromRoom(this School school,Student student)
    {
        if (student == null) throw new ArgumentNullException("student");
        if (school == null) throw new ArgumentNullException("school");
        bool ret = false;
        var room = school.Classrooms.SingleOrDefault(cr=>cr.Students.Contains(student));
        if (room !=null)
        {
            ret = true;
            room.Students.Remove(student);
        }
    
        return ret;
    }
    

    用法

    instanceOfSchool.RemoveStudentFromRoom(student);
    

    【讨论】:

    • +1,我也将其作为扩展方法。感谢您的贡献。
    猜你喜欢
    • 1970-01-01
    • 2021-10-20
    • 2017-09-12
    • 1970-01-01
    • 2010-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多