首页 > 解决方案 > groupby 以展平列表

问题描述

我有一个学生名单,如下所示:

List<Student> students = new List<Student>()
{
   new Student(){StudentId = 1, StudentName = "Alex", Grade = "FirstGrade", Marks = 98},
   new Student(){StudentId = 1, StudentName = "Alex", Grade = "SecondGrade", Marks = 92},
   new Student(){StudentId = 1, StudentName = "Alex", Grade = "ThirdGrade", Marks = 95},

   new Student(){StudentId = 2, StudentName = "Karen", Grade = "FirstGrade", Marks = 94},
   new Student(){StudentId = 2, StudentName = "Karen", Grade = "SecondGrade", Marks = 95},
   new Student(){StudentId = 2, StudentName = "Karen", Grade = "ThirdGrade", Marks = 94},

   new Student(){StudentId = 3, StudentName = "Nicole", Grade = "FirstGrade", Marks = 91},
   new Student(){StudentId = 3, StudentName = "Nicole", Grade = "SecondGrade", Marks = 99},
   new Student(){StudentId = 3, StudentName = "Nicole", Grade = "ThirdGrade", Marks = 97},
}; 

我想将students列表转换为studentReport如下所示的列表:

{ StudentId = 1, StudentName = "Alex", FirstGrade = 98, SecondGrade = 92, ThirdGrade = 95},
{ StudentId = 2, StudentName = "Karen", FirstGrade = 94, SecondGrade = 95, ThirdGrade = 94},
{ StudentId = 3, StudentName = "Nicole", FirstGrade = 91, SecondGrade = 99, ThirdGrade = 97}

我能够使用这个来实现这一点:

var studentReports = students.GroupBy(student => new { student.StudentId, student.StudentName })
        .Select(group => new Report()
        {
          StudentId = group.Key.StudentId,
          StudentName = group.Key.StudentName,
          FirstGrade = group.Where(student => student.Grade == "FirstGrade").FirstOrDefault().Marks,
          SecondGrade = group.Where(student => student.Grade == "SecondGrade").FirstOrDefault().Marks,
          ThirdGrade = group.Where(student => student.Grade == "ThirdGrade").FirstOrDefault().Marks
        });

有没有更好的方法来做到这一点?

标签: c#linq

解决方案


评估这种可能的重构:

students.GroupBy(x => x.StudentId).Select(GetReport());

选择的静态函数:

    static Func<IGrouping<int, Student>, Report> GetReport() => group =>
    {
        var report = new Report
        {
            StudentId = group.Key,
            StudentName = group.First().StudentName,
        };

        foreach (var student in group)
            report.SetGrade(student);

        return report;
    };

具体报告等级“二传手”:

    public class Report
    {
        public void SetGrade(Student student)
        {
            switch (student.Grade)
            {
                case "FirstGrade":
                    FirstGrade = student.Marks; break;
                case "SecondGrade":
                    SecondGrade= student.Marks; break;
                case "ThirdGrade":
                    ThirdGrade= student.Marks; break;
            }
        }
        [...props...]
    }

推荐阅读