在 C# 中使用 LINQ 按范围排序列表
Posted
技术标签:
【中文标题】在 C# 中使用 LINQ 按范围排序列表【英文标题】:Sorting list by range using LINQ in C# 【发布时间】: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 计算范围数。
我想学习怎么做。
【问题讨论】:
【参考方案1】:您可以结合使用 LINQ 的 Average
、Select
和 GroupBy
,以及一些算术:
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();
【讨论】:
以上是关于在 C# 中使用 LINQ 按范围排序列表的主要内容,如果未能解决你的问题,请参考以下文章