簡體   English   中英

如何按集合分組成為集合的可枚舉

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM