2010-10-19 9 views
6

Mi ejemplo particular es bastante complejo, pero creo que el concepto se aplicaría igualmente a algo así como un sistema de registro, por lo que lo usaré para facilitar la explicación. Es un ejemplo ficticio, por favor no insistir en o agonizan por lo que es achitectually, mediante programación o moralmente malo con el ejemplo propio :)LINQ: Seleccione de IEnumerable con Distinct/GroupBy y clasificación - posible?

Digamos que tiene esto:

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

y que se han retirado un conjunto de los datos como este:

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 

lo que quiero hacer es seleccionar sólo el último registro único (es decir, en la marca de hora Ordenar Descendente) para cada usuario (es decir GroupBy nombre de usuario). Puedo entender Distinct, y en menor medida GroupBy, pero combinar todos estos en una declaración única que también devuelve los campos/propiedades no diferenciadas/agrupadas Y clasifica por timestamp me está dando dolor de cabeza.

Lo que debería salir con el ejemplo anterior es:

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 

no quiero a 'engañar' y recurrir a una forma de largo aliento de hacerlo cuando el rendimiento no es crítico aquí y yo Estoy moderadamente seguro de que se puede hacer en una sola declaración LINQ.

+0

¿Cómo quieres que sea el último tipo? – Will

Respuesta

14

Espero que mi LINQ-fu es correcto en este caso: =)

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

Este código de ejemplo el uso de sus datos y ordenamiento final por ID, da exactamente el mismo resultado que el ejemplo: (si no '¡no importa el formato crudo!)

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

me queda bien. Aunque parece estar ordenado por 'ID' al final. –

+0

¡Leyenda! Gracias. Es frustrante lo difícil que es encontrar ejemplos simples que no sean> demasiado nathanchere

+0

@Jeff: Saludos. Le pedí al OP que aclare este punto. – Will

Cuestiones relacionadas