簡體   English   中英

在 C# 中使用 LINQ 按范圍排序列表

[英]Sorting list by range using LINQ in C#

我有一個這樣的列表:

            List<Student> students = new List<Student>
            {
                new Student { Name = "M", Scores = new int[] { 94, 92, 91, 91 } },
                new Student { Name = "I", Scores = new int[] { 66, 87, 65, 93, 86} },
                new Student { Name = "C", Scores = new int[] { 76, 61, 73, 66, 54} },
                new Student { Name = "D", Scores = new int[] { 94, 55, 82, 62, 52} },
                new Student { Name = "P", Scores = new int[] { 91, 79, 58, 63, 55} },
                new Student { Name = "E", Scores = new int[] { 74, 85, 73, 75, 86} },
                new Student { Name = "P", Scores = new int[] { 73, 64, 53, 72, 68} },
            }

有什么方法可以計算每個學生的平均分並按范圍顯示。 結果將是這樣的:

Score > 90 and < 100
 M(student name) 92 (average score)
Score > 80 and < 90
 P 86.8
 I 83.4
 Y 82.4

我還需要計算有多少范圍。 例如,對於上述結果,我們有兩個范圍:(>90 和 <100) 和 (>80 和 <90)。

我已經知道如何計算平均分數,但是我堅持將它們分組到范圍內並僅使用 LINQ 計算范圍數。

我想學習如何做。

您可以結合使用 LINQ 的AverageSelectGroupBy ,以及一些算法:

var result = string.Join("\r\n",
    students.Select(s =>
        (s.Name, Average: s.Scores.Average(sc => (double)sc)))
    .GroupBy(s => (int)Math.Ceiling(s.Average / 10))
    .OrderByDescending(g => g.Key)
    .Select(g =>
        $"Score >= {g.Key * 10 - 10} and < {g.Key * 10}\r\n"
        + string.Join("\r\n", g.Select(s => $" {s.Name} {s.Average:F1}"))
    );

或者略有不同

var result = string.Join("\r\n",
    students.Select(s =>
        (s.Name, Average: s.Scores.Average(sc => (double)sc)))
    .GroupBy(s => (int)Math.Ceiling(s.Average / 10))
    .OrderByDescending(g => g.Key)
    .SelectMany(g =>
        g.Select(s => $" {s.Name} {s.Average:F1}")
         .Prepend($"Score >= {g.Key * 10 - 10} and < {g.Key * 10}\r\n"))
    );

首先,請注意,您將需要一個平均分數剛好為 90 的案例。我假設這將由較高的存儲桶處理,但如果您需要較低的存儲桶,您可以更改邏輯。

最好按分數的“等級字母”計算和分組,因為它是一個字母,字母很容易按字母順序排列。

var studentsByGrade = students
    .Select(x => new {
        x.Name,
        AvgScore = x.Scores.Average()
    })
    .GroupBy(x => GetGradeLetter(x.AvgScore));

這將使用輔助方法。

private static string GetGradeLetter(double score)
{
    if (score is >= 90)
        return "A";
    
    if (score is >= 80)
        return "B";

    // add more as you'd like
    
    return "ZZZ";
}

值得注意的是,您不需要在此處顯示字母 - 使用它只是因為它便於訂購,而且很可能這就是您最終會使用的。 通常,您會將低於“60”的任何事物標記為一組,因為(至少在美國學校系統中)這意味着“F”。

要顯示結果,請使用兩個 foreach。

foreach (var grade in studentsByGrade.OrderBy(x => x.Key))
{
    foreach (var student in grade.OrderByDescending(x => x.AvgScore))
    {
        Console.WriteLine($"{student.Name} {student.AvgScore}");
    }
    Console.WriteLine();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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