chirag_lad
chirag_lad

Reputation: 249

groupby to flatten list

I have a list of students which looks like this:

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},
}; 

I want to convert students list to studentReport list which looks like this:

{ 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}

I was able to achieve that using this:

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
        });

Is there any better way of doing this?

Upvotes: 2

Views: 98

Answers (1)

Simone S.
Simone S.

Reputation: 1916

Evaluate this possible refactoring:

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

static func for select:

    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;
    };

specific report grades "setter":

    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...]
    }

Upvotes: 1

Related Questions