我有一个简单的 POCO 课程,其中包含学生的分数。
For example:
Math - 83%
Engrish - 82%
Chemistry - 81%
Drama - 100%
etc..
有没有办法(使用LINQ?)我可以找出按分数排序的前 3 个属性?
我假设最终对象将是匿名类型的 IList<T>,它将有两个字段。
- 名称(属性的名称)
- 分数(十进制值)。
对象中的属性数量是有限的:)
有什么建议么?
作为替代答案,这可以在数据库中完成吗?
你在寻找这样的东西吗?
class Notes
{
public double Math{ get; set; }
public double English { get; set; }
public double Chemistry { get; set; }
public double Drama { get; set; }
public string IgnoreMePlease { get; set; }
}
class Program
{
static void PrintHighestNotes(Notes notes)
{
var pairs = from property in notes.GetType().GetProperties()
where property.PropertyType == typeof (double)
select new
{
Name = property.Name,
Value = (double) property.GetValue(notes, null)
};
var result = pairs.OrderByDescending(pair => pair.Value);
foreach (var pair in result)
Console.WriteLine("{0} = {1}", pair.Name, pair.Value);
}
static void Main(string[] args)
{
Notes notes = new Notes()
{
Chemistry = 0.10,
Math = 0.2,
Drama = 1,
English = 0.3,
IgnoreMePlease = "Ignore"
};
PrintHighestNotes(notes);
}
}
除非您碰巧在内存中拥有所有数据,否则让数据库为您选择正确的数据会更有效。
如果将成绩作为字段存储在数据库中,则必须对其进行规范化以使其可以查询。最好的办法是重新设计数据库并将成绩作为行放在单独的表中。数据应该在表格的字段中,而不是作为字段名称:
select top 3 GradeName, Grade
from Grades
where StudentId = 42
order by Grade desc
您还可以动态规范化数据,但这当然效率不高:
select top 3 GradeName, Grade
from (
select GradeName = 'Engrish', Grade = Engrish from Students where StudentId = 42
union all
select 'Drama', Drama from Students where StudentId = 42
union all
select 'Math', Math from Students where StudentId = 42
union all
select 'Chemistry', Chemistry from Students where StudentId = 42
) Grades
order by Grade desc
使用以主题为键、分数为值的字典会更简单:
Dictionary<string, int> scores = new Dictionary<string, int>();
...
var top3Subjects = (from s in scores
orderby s.Value descending
select s).Take(3);
这将返回一个IEnumerable<KeyValuePair<string, int>>
,您可以像这样使用它:
foreach (var s in top3Subjects)
{
Console.WriteLine("{0} : {1}", s.Key, s.Value);
}
您的问题不清楚分数是所有单独的属性还是某种列表。如果他们是一个列表,这将工作:
var topScores =
(from s in Scores
orderby s.Score descending
select new { s.Name, s.Score}).Take(3);