Reputation: 420
I'm trying to learn Linq and I need help with a method that searches a List within a List, finds a match, and deletes it. For example, imagine I have a class called Student
:
public class Student
{
string FirstName;
string LastName;
}
Then imagine I have another class called Classroom
, which has a List<Student>
:
public class Classroom
{
List<Student> Students;
}
And finally, I have one more class, called School
, which has a list of Classrooms
:
public class School
{
List<Classroom> Classrooms;
}
Then, I need a method that takes in a Student
object, checks to see if the student is in the school, and deletes them if they are. If they're in the school, the method should delete them and return true. If they're not in the school, the method should return false and take no action. Here's an example using foreach loops, which I want to get rid of:
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;
}
Upvotes: 1
Views: 2943
Reputation: 16018
What about an extension method..
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;
}
Usage
student.RemoveFromRoom(instanceOfSchool);
Or...
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;
}
Usage
instanceOfSchool.RemoveStudentFromRoom(student);
Upvotes: 1
Reputation: 19020
This assumes a student can only be in one room and Student
is IEquatable
on first and last name (or the references are equal):
var roomWithStudent = Classrooms.FirstOrDefault(c => c.Students.Any(s => s.Equals(student));
if (roomWithStudent != null)
{
roomWithStudent.Remove(student);
return true;
}
return false;
An alternative approach if Student
is not IEquatable
and the search object passed in is not necessarily the same reference:
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;
Upvotes: 3