I need to add GroupID
to students that have duplicate School
and duplicate Age
(Steve, Bill, Rich, Robert). Output needs to be cast in the original list format (List<Student>
).
List<Student> studentList = new List<Student>() {
new Student() { StudentID = 1, StudentName = "John", Age = 18, School = "ABC" , GroupID = 0} ,
new Student() { StudentID = 2, StudentName = "Steve", Age = 21, School = "DEF", GroupID = 0 } ,
new Student() { StudentID = 3, StudentName = "Bill", Age = 21, School = "DEF", GroupID = 0 } ,
new Student() { StudentID = 4, StudentName = "Josh" , Age = 20, School = "DEF", GroupID = 0 },
new Student() { StudentID = 5, StudentName = "Jack" , Age = 19, School = "JKL", GroupID = 0 },
new Student() { StudentID = 6, StudentName = "Thomas" , Age = 18, School = "MNO", GroupID = 0 },
new Student() { StudentID = 7, StudentName = "Rich" , Age = 22, School = "PQR", GroupID = 0 },
new Student() { StudentID = 8, StudentName = "Robert" , Age = 22, School = "PQR", GroupID = 0 },
new Student() { StudentID = 9, StudentName = "John" , Age = 20, School = "PQR", GroupID = 0 },
new Student() { StudentID = 10, StudentName = "Emma" , Age = 20, School = "XYZ", GroupID = 0 }};
List<Student> outputList = studentList
.GroupBy(s => new { s.Age, s.School })
.Where(g => g.Count() >= 2)
.SelectMany(g => g)
.ToList();
Output:
Steve & Bill:
GroupID = 1
Rich & Robert:
GroupID = 2
Any help is appreciated.
CodePudding user response:
SelectMany
has an overload that passes in the index of the item so you could do this:
List<Student> outputList = studentList
.GroupBy(s => new { s.Age, s.School })
.Where(g => g.Count() >= 2)
.SelectMany((g, i) => g.Select(s =>
{
s.GroupID = i;
return s;
}))
.ToList();
That does feel a little hacky (I don't like mutating objects in Linq) so I would probably do something like this:
List<Student> outputList = studentList
.GroupBy(s => new { s.Age, s.School })
.Where(g => g.Count() >= 2)
.SelectMany((g, i) => g.Select(s => new Student
{
StudentID = s.StudentID,
StudentName = s.StudentName,
Age = s.Age,
School = s.School,
GroupID = i
}))
.ToList();
CodePudding user response:
There are other ways to do this, however, why not Just use an old school loop ?
var outputList = studentList
.GroupBy(s => new { s.Age, s.School })
.Where(g => g.Count() >= 2)
.ToList();
var count = 0;
foreach (var students in outputList)
{
count ;
foreach (var student in students)
student.GroupID = count;
}
var result = outputList.SelectMany(x => x);
CodePudding user response:
var gp = studentList
.GroupBy(s => new { s.Age, s.School })
.Select((x, y) =>
new
{
GroupId = y,
Students = x.Select(o => new Student{Age = o.Age ...
})
}).ToList();
CodePudding user response:
If you want to use LINQ, one way would be to add this method in your Student
class:
public Student SetGroupId(int id)
{
this.GroupID = id;
return this;
}
Then, you can create the output list like this:
List<Student> outputList = studentList
.GroupBy(s => new { s.Age, s.School })
.Where(g => g.Count() >= 2)
.SelectMany((g, i) => g.Select(s => s.SetGroupId(i 1)))
.ToList();
You could get rid of the SetGroupId
method if you want but it would be less readable, in my opinion:
List<Student> outputList = studentList
.GroupBy(s => new { s.Age, s.School })
.Where(g => g.Count() >= 2)
.SelectMany((g, i) => g.Select(s => { s.GroupID = i 1; return s; }))
.ToList();