Tentando encontrar a parte superior 3 propriedades de um exemplo POCO
Pergunta
Eu tenho uma classe POCO simples que contém pontuação do aluno.
For example:
Math - 83%
Engrish - 82%
Chemistry - 81%
Drama - 100%
etc..
Existe uma maneira (usando LINQ ?) Que eu pudesse descobrir o top 3 Propriedades ordenados por pontuação?
Estou assumindo o objeto final será um IList
- Name (o nome da propriedade)
- Score (o valor decimal).
O número de propriedades do objecto são finitas embora:)
Todas as sugestões?
Como uma resposta alternativa, isso poderia ser feito em um banco de dados em vez disso?
Solução
Você está procurando algo parecido com isto?
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);
}
}
Outras dicas
A menos que você já acontecer de ter todos os dados na memória, é mais eficiente para deixar o banco de dados, selecione os dados corretos para você.
Se você armazenar as notas como campos no banco de dados, você tem que normalizá-lo para torná-lo possível para consulta. O melhor é redesenhar o banco de dados e colocar as notas como linhas em uma tabela separada. Os dados devem estar nos campos das tabelas, não como nomes de campo:
select top 3 GradeName, Grade
from Grades
where StudentId = 42
order by Grade desc
Você também pode normalizar os dados em tempo real, mas que é, naturalmente, não tão eficiente:
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
Seria mais simples de usar um dicionário com o assunto como a chave e o marcador quando o valor:
Dictionary<string, int> scores = new Dictionary<string, int>();
...
var top3Subjects = (from s in scores
orderby s.Value descending
select s).Take(3);
Isso retorna uma IEnumerable<KeyValuePair<string, int>>
, que você pode usar como esta:
foreach (var s in top3Subjects)
{
Console.WriteLine("{0} : {1}", s.Key, s.Value);
}
Não está claro na sua pergunta se as pontuações são todas as propriedades separadas ou se é algum tipo de lista. Se eles são uma lista, isso iria funcionar:
var topScores =
(from s in Scores
orderby s.Score descending
select new { s.Name, s.Score}).Take(3);