LINQ创建子对象列表的唯一值

时间:2017-01-26 00:09:48

标签: c# linq

我有一个课程列表,其中课程对象如下所示:

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对象。

我在这里做错了什么?

2 个答案:

答案 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此解决方案不需要实施。