[英]How to group by a collection to be an Enumerable of collection
我有一個集合,其中包含一個實現以下屬性的集合。 這是一個例子:
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 歲]
雪利酒:[雪利酒,英語,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);
這構成了一個組序列。 每個組都有一個字符串屬性 Key,它是組中所有學生的通用名稱。 該組也是一系列學生(請注意:IS 沒有)。 組中的每個Student都有相同的Student.Name值,即Key的值。
這看起來幾乎就像您想要實現的目標。 您的代碼的大多數讀者都知道 GroupBy,並且他們期望 IGrouping。 所以考慮使用它作為結果。
但是,如果您真的想要一個對象序列,其中每個 object 都有一個字符串屬性 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,
})
這會給你你想要的。 但是,它效率不高:有 25 個元素的學生群“Charla”的名稱“Charla”是“Charla”的 26 倍。 最好不要一遍又一遍地 select 這個名字:
// resultSelector
(commonName, studentsWithThisName) => new
{
Name = commonName,
Grades = studentsWithThisName.Select(student => new
{
Subject = student.Subject,
Grade = student.Grade,
}
.ToList()
}
現在你真的有一系列學生和他們的成績。
您確定學生姓名是唯一的嗎? 您的收藏中不會有兩個名為“John Doe”的學生嗎? 如果您處於仍然可以更改學生的開發階段,請考慮為每個學生提供一個唯一的 ID,類似於數據庫中發生的情況。
如果您將長時間使用這種設計,並且會創建大量學生和成績,如果您已經有數千個學生成績,那么將您的數據分成幾張表將為您帶來很多麻煩,並且突然你得到一個名字已經存在的新學生。 這也將減少人們輸入錯誤的可能性(“Mash”而不是“Math”),即使他們這樣做了,也只需在一個地方進行更改。
我也看到使用雙精度等級的問題。 最好使用小數。 如果您確定成績在小數點后的位數有限,那么在相等比較中,小數比雙精度要好得多。 因此,如果您需要讓學生的成績等於 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;}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.