Prova di trovare le prime 3 proprietà di un'istanza POCO
Domanda
Ho una semplice classe POCO che contiene i punteggi degli studenti.
For example:
Math - 83%
Engrish - 82%
Chemistry - 81%
Drama - 100%
etc..
Esiste un modo (usando LINQ ?) che potrei capire i primi 3 proprietà ordinate per punteggio?
Suppongo che l'oggetto finale sarà un IList < T > di tipo anonimo, che avrà due campi.
- Nome (il nome della proprietà)
- Punteggio (il valore decimale).
Il numero di proprietà nell'oggetto è finito però :)
Qualche suggerimento?
In alternativa, è possibile farlo in un database?
Soluzione
Stai cercando qualcosa del genere?
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);
}
}
Altri suggerimenti
A meno che tu non abbia già tutti i dati in memoria, è più efficiente consentire al database di selezionare i dati corretti per te.
Se si memorizzano i voti come campi nel database, è necessario normalizzarli per rendere possibile l'interrogazione. La cosa migliore è riprogettare il database e inserire i voti come righe in una tabella separata. I dati dovrebbero essere nei campi delle tabelle, non come nomi dei campi:
select top 3 GradeName, Grade
from Grades
where StudentId = 42
order by Grade desc
Puoi anche normalizzare i dati al volo, ma ovviamente non è altrettanto efficiente:
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
Sarebbe più semplice usare un dizionario con l'oggetto come chiave e il punteggio come valore:
Dictionary<string, int> scores = new Dictionary<string, int>();
...
var top3Subjects = (from s in scores
orderby s.Value descending
select s).Take(3);
Questo restituisce un IEnumerable<KeyValuePair<string, int>>
, che puoi usare in questo modo:
foreach (var s in top3Subjects)
{
Console.WriteLine("{0} : {1}", s.Key, s.Value);
}
Non è chiaro nella tua domanda se i punteggi sono tutte proprietà separate o se sono una specie di elenco. Se sono un elenco, questo funzionerebbe:
var topScores =
(from s in Scores
orderby s.Score descending
select new { s.Name, s.Score}).Take(3);