2010-01-25 8 views
16

que tienen una serie de clases con una propiedad Date, es decir .:¿Encontrar la fecha mínima y máxima en la matriz usando LINQ?

class Record 
{ 
    public DateTime Date { get; private set; } 
} 

void Summarize(Record[] arr) 
{ 
    foreach (var r in arr) 
    { 
     // do stuff 
    } 
} 

tengo que encontrar la earliest (mínimo) y las fechas latest (máximo) de esta matriz.

¿Cómo puedo hacer eso usando LINQ?

+1

"eficiente" y "óptima" la necesidad de un contexto. ¿Prefiere un algoritmo que sea eficiente en cuanto a espacio (uso de memoria, tamaño de código) o tiempo (tiempo de ejecución, tiempo de compilación)? – EricSchaefer

Respuesta

38

Si usted quiere encontrar la primera o la última Fecha:

DateTime earliest = arr.Min(record => record.Date); 
DateTime latest = arr.Max(record => record.Date); 

Enumerable.Min, Enumerable.Max


Si desea encontrar el registro con la primera o la última Fecha:

Record earliest = arr.MinBy(record => record.Date); 
Record latest = arr.MaxBy(record => record.Date); 

Ver: How to use LINQ to select object with minimum or maximum property value

+3

Definitivamente la forma más fácil de hacerlo. En términos de eficiencia pura que no sería la más eficiente. Sin embargo, dudo que este código sea un cuello de botella. –

+0

@Keith Rousseau: ¿Por qué te hace pensar que este no sería el "más eficiente"? –

+4

@drj: itera la matriz dos veces. La misma complejidad, el factor constante se duplicó, sin embargo. – Joey

12

solución de edad escolar sin LINQ:

DateTime minDate = DateTime.MaxValue; 
DateTime maxDate = DateTime.MinValue; 
foreach (var r in arr) 
{ 
    if (minDate > r.Date) 
    { 
     minDate = r.Date; 
    } 
    if (maxDate < r.Date) 
    { 
     maxDate = r.Date; 
    } 
} 
+6

bien, para el downvoter: la consulta original era: 'con C#', y fue editada a 'con LINQ' – Natrium

+0

De hecho, se confundió: (minDate> r.Date) y (maxDate abatishchev

+1

@abatishchev: tiene toda la razón y corregí esto. – Natrium

1

Uso de expresiones lambda:

void Summarise(Record[] arr) 
{ 
    if (!(arr == null || arr.Length == 0)) 
    { 
     List<Record> recordList = new List<Record>(arr); 
     recordList.Sort((x,y) => { return x.Date.CompareTo(y.Date); }); 

     // I may have this the wrong way round, but you get the idea. 
     DateTime earliest = recordList[0]; 
     DateTime latest = recordList[recordList.Count]; 
    } 
} 

Esencialmente:

  • Ordenar en una nueva lista en orden de fecha
  • Seleccione el primer y último elemento de esa lista

ACTUALIZACIÓN: Pensando en ello, no estoy seguro de que esta es la manera de hacerlo si usted se preocupa en absoluto sobre el rendimiento, como ordenar la lista entera dará lugar a muchas más comparaciones que simplemente escaneando para el valores más altos/más bajos.

1

Me gustaría hacer dos propiedades Min, Max, asignarles el valor del primer elemento que agregue a la matriz, cada vez que agregue un nuevo elemento simplemente compruebe si su DateTime es menor o mayor que el Min Max unos.

Es agradable y rápido, y será mucho más rápido que iterar a través de la matriz cada vez que necesite obtener Min Max.

3

Los dos en una consulta LINQ (y uno transversal):

arr.Aggregate(
    new { MinDate = DateTime.MaxValue, 
      MaxDate = DateTime.MaxValue }, 
    (accDates, record) => 
     new { MinDate = record.Date < accDates.MinDate 
         ? record.Date 
         : accDates.MinDate, 
       MaxDate = accDates.MaxDate < record.Date 
         ? record.Date 
         : accDates.MaxDate }); 
+0

¡Muy interesante! ¿Podrías mirar mi siguiente pregunta? Http://stackoverflow.com/questions/2138391/how-to-rewrite-several-independent-linq-quries-into-single-one-using-aggregate Estaré feliz si pudieras respóndelo y podría aceptarlo. – abatishchev

Cuestiones relacionadas