我有一个实现以下属性的集合.这里是一个例子。
class Student {public string Name, public string Subject, public double Grade }
在自定义查询之后,我有一个学生的集合作为返回值
IEnumerable<Student> studentList
它有多个项目的所有学生信息与重复的名称如下内容。
[Charla, English, 92]
[Charla, Math, 64]
[Sherry, English, 91]
[Sherry, Math, 70]
我想实现一个linq查询,以组这个列表的名称和返回。
IEnumerable<Name, IEnumerable<Student>> studentListGropByName
夏拉:【夏拉,英语,92】【夏拉,数学,64】。
Sherry: [雪莉,英语,91] [雪莉,数学,70]
其他名称:...
有没有什么可能的查询来实现?
考虑使用一个重载的 GroupBy.
使用 GroupBy,您可以创建学生组,其中同一组中的所有学生都具有一个或多个属性的相同值。这个相同的值被称为 Key。
GroupBy 的参数之一是 KeySelector。这个参数定义了一个组中所有学生应该具有的共同属性值。
哟要制作学生组,组中每个键为 "X "的学生的属性值Student.Name等于 "X"。
IEnumerable<Student> ungroupedStudents = ...
IEnumerable<IGrouping<string, Student> studentsGroupedByName = ungroupedStudents.GroupBy(
// KeySelector: make groups of students with same name:
student => student.Name);
这就形成了一个组的序列 每个Group都有一个字符串属性Key,它是该组中所有学生的共同名称。该组也是一个学生序列(要注意:是IS不是HAS)。组中的每个学生都有相同的Student.Name的值,即Key的值。
这看起来几乎就像你想实现的那样。你的代码的大多数读者都会知道GroupBy,他们期待一个IGrouping。所以考虑使用这个作为结果。
然而,如果你真的想要一个对象序列,其中每个对象都有一个字符串属性Name和一个属性Students,可以考虑使用GroupBy的其他重载,一个有参数resultSelector的重载。
var studentsGroupedByName = ungroupedStudents.GroupBy(
// keySelector: make groups of students with same name:
student => student.Name,
// resultSelector: from every common name, and all students with this name
// make one new object:
(commonName, studentsWithThisName) => new
{
Name = commonName,
Students = studentsWithThisName,
})
这将给你你想要的东西。然而,它的效率并不高:学生组 "Charla "有25个元素,而名字 "Charla "有26次。最好不要重复选择这个名字。
// resultSelector
(commonName, studentsWithThisName) => new
{
Name = commonName,
Grades = studentsWithThisName.Select(student => new
{
Subject = student.Subject,
Grade = student.Grade,
}
.ToList()
}
现在你真的有了一个学生和他们的等级的序列。
你确定学生的名字是独一无二的吗?您的收藏中不会有两个叫 "John Doe "的学生?如果您在开发阶段仍然可以更改学生,请考虑给每个学生一个唯一的ID,类似于数据库中的情况。
如果您将在较长的时间内使用这种设计,并将创建大量的学生和年级,将您的数据分割成几个表将使您在未来的工作中避免很多麻烦,如果您已经有数千名学生的成绩,而您突然得到一个新的学生,而他的名字已经存在。这也会使人们不太可能犯打字错误("Mash "而不是 "Math"),即使他们犯了错误,也只需要在一个地方改变。
我也觉得用双数来表示 "Grade "有问题。最好使用十进制。如果你确定Grade在小数点后的位数有限,那么在平等比较中,小数比双数要好得多。所以,如果你需要得到等级等于4.7的学生,小数是更好的方法,特别是如果你使用计算来得到这个值。
class Student
{
public int Id {get; set;}
public string Name {get; set;}
}
public class Grades
{
public int Id {get; set;}
public decimal Grade {get; set;}
... // other properties, for example
public DateTime Date {get; set;}
// foreign keys
public int StudentId {get; set;}
public int SubjectId {get; set;}
}
public class Subject
{
public int Id {get; set;}
public string Name {get; set;}
... // other properties, for instance:
public string description {get; set;}
}