【问题标题】:Sorting list by range using LINQ in C#在 C# 中使用 LINQ 按范围排序列表
【发布时间】:2021-11-24 00:52:34
【问题描述】:

我有一个这样的列表:

            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 和 80 和

我已经知道如何计算平均分数,但是我坚持将它们分组到范围中并仅使用 LINQ 计算范围数。

我想学习怎么做。

【问题讨论】:

    标签: c# list linq


    【解决方案1】:

    您可以结合使用 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"))
        );
    

    【讨论】:

    • 我尝试导入代码,Average出现错误,错误为“当前上下文中不存在Average的名称”。
    • 抱歉现在应该修复
    • 非常感谢。运行后,建议你将 $"Score >= {g.Key * 10} 和 = {g.Key * 10 - 10} 和
    【解决方案2】:

    首先,请注意,当平均分正好是 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”。

    要显示结果,请使用两个 foreaches。

    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();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-01
      • 1970-01-01
      • 2019-06-28
      • 2021-10-23
      • 2013-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多