2010-10-19 10 views
6

Il mio esempio particolare è piuttosto complesso ma penso che il concetto si applicherebbe ugualmente a qualcosa come un sistema di registrazione, quindi lo userò per facilitare la spiegazione. E 'un esempio fittizio, si prega di non arpa o agonizzare su ciò che è achitectually, programmaticamente o moralmente sbagliato con l'esempio stesso :)LINQ: Seleziona da IEnumerable con Distinct/GroupBy e ordinamento - possibile?

Diciamo che avete questo:

class LogEntry 
{ 
    int ID; 
    int UserName; 
    datetime TimeStamp; 
    string Details; 
} 

e si è tirato un set dei dati di questo tipo:

ID Username Timestamp Details 
1 foo  1/01/2010 Account created 
2 zip  2/02/2010 Account created 
3 bar  2/02/2010 Account created 
4 sandwich 3/03/2010 Account created 
5 bar  5/05/2010 Stole food 
6 foo  5/05/2010 Can't find food 
7 sandwich 8/08/2010 Donated food 
8 sandwich 9/09/2010 Ate more food 
9 foo  9/09/2010 Ate food 
10 bar  11/11/2010 Can't find food 

Quello che voglio fare è selezionare solo l'ultimo singolo record (cioè Ordina su TimeStamp Discendente) per ogni utente (ad esempio GroupBy Nome utente). Posso capire meglio Distinct, e in misura minore GroupBy, ma combinare tutti questi elementi in una singola istruzione che restituisce anche i campi/proprietà non differenziati/raggruppati e le ordinanze per data e ora mi dà fastidio.

Cosa dovrebbe uscire con l'esempio sopra è:

ID Username Timestamp Details 
2 zip  2/02/2010 Account created 
8 sandwich 9/09/2010 Ate more food 
9 foo  9/09/2010 Ate food 
10 bar  11/11/2010 Can't find food 

Non voglio a 'imbrogliare' e ricorrere a un modo prolisso di farlo quando le prestazioni non è critico qui e mi Sono moderatamente fiducioso che può essere fatto in una singola istruzione LINQ.

+0

Come si desidera che l'ordinamento finale sia? – Will

risposta

14

Spero che la mia Linq-fu è proprio su questo: =)

var results = sourceList 
    .OrderByDescending(item => item.Timestamp) 
    .GroupBy(item => item.Username) 
    .Select(grp => grp.First()) 
    .ToArray(); 

Questo codice di esempio utilizzando i vostri dati, e l'ordinazione finale per ID, dà esattamente lo stesso output tuo esempio: (se non si 't mente la formattazione grezza!)

class Program 
{ 
    static void Main(string[] args) 
    { 
     var sourceItems = new[] { 
      new LogEntry {ID=1 ,UserName="foo  ", TimeStamp= new DateTime(2010 ,1,01),Details="Account created ",} , 
      new LogEntry {ID=2 ,UserName="zip  ", TimeStamp= new DateTime(2010 ,2,02),Details="Account created ",} , 
      new LogEntry {ID=3 ,UserName="bar  ", TimeStamp= new DateTime(2010 ,2,02),Details="Account created ",} , 
      new LogEntry {ID=4 ,UserName="sandwich ", TimeStamp= new DateTime(2010 ,3,03),Details="Account created ",} , 
      new LogEntry {ID=5 ,UserName="bar  ", TimeStamp= new DateTime(2010 ,5,05),Details="Stole food  ",} , 
      new LogEntry {ID=6 ,UserName="foo  ", TimeStamp= new DateTime(2010 ,5,05),Details="Can't find food ",} , 
      new LogEntry {ID=7 ,UserName="sandwich ", TimeStamp= new DateTime(2010 ,8,08),Details="Donated food ",} , 
      new LogEntry {ID=8 ,UserName="sandwich ", TimeStamp= new DateTime(2010 ,9,09),Details="Ate more food ",} , 
      new LogEntry {ID=9 ,UserName="foo  ", TimeStamp= new DateTime(2010 ,9,09),Details="Ate food  ",} , 
      new LogEntry {ID=10 ,UserName="bar  ", TimeStamp= new DateTime(2010,11,11),Details="Can't find food ",} , 
     }; 

     var results = sourceItems 
      .OrderByDescending(item => item.TimeStamp) 
      .GroupBy(item => item.UserName) 
      .Select(grp => grp.First()) 
      .OrderBy(item=> item.ID) 
      .ToArray(); 

     foreach (var item in results) 
     { 
      Console.WriteLine("{0} {1} {2} {3}", 
       item.ID, item.UserName, item.TimeStamp, item.Details); 
     } 
     Console.ReadKey(); 
    } 
} 


public class LogEntry 
{ 
    public int ID; 
    public string UserName; 
    public DateTime TimeStamp; 
    public string Details; 
} 
+0

Mi sembra buono. Anche se sembra essere ordinato per 'ID' alla fine. –

+0

Legenda! Grazie. È frustrante quanto sia difficile trovare esempi semplici che non siano eccessivamente semplici. – nathanchere

+0

@Jeff: Saluti - Ho chiesto al PO di chiarire questo punto. – Will