我有一个课程列表,其中课程对象如下所示:
public class Course
{
public int Id { get; set; }
public string CourseName { get; set; }
public Teacher Teacher { get; set; } = new Teacher();
}
为清楚起见,教师对象如下所示:
public class Teacher
{
public int Id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
}
我正在努力制作一份独特的老师名单。我想我几乎就在那里,但努力制作一个List。
这是我到目前为止所拥有的:
var teachers = from c in Courses // Courses is List<Course> with data in it
group c by new { c.Teacher.Id, c.Teacher.Name }
into uniqueTeachers
select uniqueTeachers.ToList();
看起来问题是我需要逐行创建一个Teacher对象。
我在这里做错了什么?
答案 0 :(得分:2)
就像BradleyDotNET用户评论的那样,你必须实现IEqualityComparar<T>
才能完成它。样本:
public class TeacherEqualityComparer : IEqualityComparer<Teacher>
{
public override bool Equals(Teacher x, Teacher y)
{
return x.Id == y.Id && x.Name == y.Name;
}
public override int GetHashCode((Teacher obj)
{
return obj == null ? 0 : obj.Id;
}
}
并尝试使用Distinct
:
var teacherComparer = new TeacherEqualityComparer();
var teachers = (from c in Courses
select c.Teacher).Distinct(teacherComparer);
答案 1 :(得分:0)
第一个Select
获取所有教师的列表(非唯一)。然后,我们GroupBy
教师ID,并在每个小组中获取教师的First
个实例。
var teachers = courses.Select (a => a.Teacher)
.GroupBy(a => a.ID)
.Select (g => g.First()).ToList();
不需要IEqualityComparer
。
LINQ?为什么不PLINQ?就像,如果你有一万亿课程,或者别的什么。
var teachers = new ConcurrentDictionary<int, Teacher>();
courses.AsParallel().ForAll(a => teachers.TryAdd(a.Teacher.ID, a.Teacher));
如果ID已经在列表中, TryAdd
将失败(但不会抛出异常),因此这将为您提供唯一性。代码完成后,您将拥有一个包含ID的字典和每个教师的对象实例。该解决方案使用多个线程,如果它会提高性能。
IEqualityComparer
此解决方案不需要实施。