2010-02-25 17 views
8

Tengo una lista que contiene Fechas:C# - Calcular min fecha/hora como máximo de una lista

List<string> StringDates; 

    [0]: "04.03.2010" 
    [1]: "09.03.2010" 
    [2]: "11.03.2010" 
    [3]: "12.03.2010" 
    [4]: "16.03.2010" 
    [5]: "18.03.2010" 
    [6]: "19.03.2010" 
    [7]: "23.03.2010" 
    [8]: "25.03.2010" 
    [9]: "26.03.2010" 

Utilizando C# ¿cuál es la mejor manera/más corto para averiguar la fecha min fecha/max de esta lista?

Respuesta

17

Me gusta la solución simple.

DateTime minDate = DateTime.MaxValue; 
DateTime maxDate = DateTime.MinValue; 
foreach (string dateString in StringDates) 
{ 
    DateTime date = DateTime.Parse(dateString); 
    if (date < minDate) 
     minDate = date; 
    if (date > maxDate) 
     maxDate = date; 
} 
+0

De hecho, comencé a escribir el mismo método, no creo que se pueda hacer mucho para superar el tiempo 'O (n)' a menos que lo pongas en algún tipo de estructura de montón que te permita resolverlo en 'O (logN)' tiempo, pero luego cambiaría ciclos de procesador que son increíblemente baratos para el doble de almacenamiento de memoria que es menos barato comparativamente. –

+1

@Jeffrey: ¡Tenga cuidado con la globalización del formato de fecha y hora para las fechas representadas como cadenas! – t0mm13b

+0

@ tommieb75 - Sí, pensé en eso, pero no lo incluí, porque estaba siendo flojo. Esa parte puede tomarse de la respuesta de Mark Byers. Le daré un voto favorable para el artículo de ParseExact, y lo llamaré hecho. :-) –

2

Via LINQ, que puede hacer:

from row in StringDates 
group row by true into r 
select new { 
    min = r.Min(z => z), 
    max = r.Max(z => z) 
} 
+2

La lista es una lista de '' . Las cadenas mínima y máxima no representarán necesariamente las fechas mínima y máxima. – LukeH

17

utilizar LINQ !:

var list = new List<DateTime>(); 
    list.Add(new DateTime(2010, 1, 1)); 
    list.Add(new DateTime(2008, 1, 1)); 
    list.Add(new DateTime(2009, 1, 1)); 
    Console.WriteLine(list.Max(date => date)); 
    Console.WriteLine(list.Min(date => date)); 
24

convertirlos a DateTime usando ParseExact (o TryParseExact) y luego usar LINQ para obtener el mínimo y máximo:

List<DateTime> dates = StringDates 
    .Select(x => DateTime.ParseExact(x, "dd.MM.yyyy", null)) 
    .ToList(); 
DateTime minDate = dates.Min(); 
DateTime maxDate = dates.Max(); 

Tenga en cuenta que en su ejemplo la lista ya se ordena en orden ascendente. Si puede garantizar que este será siempre el caso y desea un mejor rendimiento, podría simplemente tomar el primer y último elemento que sería O (1) en lugar de O (n). Pero lo anterior es más seguro, por lo que incluso si su lista probablemente siempre será ordenada, probablemente no debería hacer esta optimización a menos que realmente la necesite, por si acaso algún día la lista no viene en orden.

0

Esto es similar a @ respuesta, pero en vez de analizar cada fecha de Jeffrey, primero se encuentra el mínimo y el máximo fechas en la comparación de sus valores de cadena, y luego analiza los valores al final.

// This method handles the date comparisons 
private int WeirdComparer(string strDate1, string strDate2) 
{ 
    int res = string.Compare(strDate1, 6, strDate2, 6, 4); 
    if (res == 0) 
     res = string.Compare(strDate1, 3, strDate2, 3, 2); 
    if (res == 0) 
     res = string.Compare(strDate1, 0, strDate2, 0, 2); 
    return res; 
} 

public void FindMinAndMaxDates(IList<string> strDates, out DateTime minDate, out DateTime maxDate) 
{ 
    string min = "99.99.9999"; 
    string max = "00.00.0000"; 
    foreach (string strDate in strDates) 
    { 
     if (WeirdComparer(strDate, min) < 0) 
      min = strDate; 
     if (WeirdComparer(strDate, max) > 0) 
      max = strDate; 
    } 
    minDate = DateTime.ParseExact(min, "dd.MM.yyyy", null); 
    maxDate = DateTime.ParseExact(max, "dd.MM.yyyy", null); 
} 
+0

Este 'FindMinAndMaxDates' tiene un' IList 'como entrada. ¿Cómo representarías un DateTime nulo?Como una cadena nula? Tendría que cambiar el WeirdComparer para manejar fechas nulas, también usar una semántica consistente de comparación de fechas nulas, y finalmente omitir el ParseExact si la fecha mínima/máxima es nula. – Fede

+0

No usar cadena, solo usando *** DateTime nullable *** tipo – Kiquenet

+1

En ese caso no necesita la función 'WeirdComparer'. Puede escaparse fácilmente utilizando el comparador predeterminado para 'DateTime?'. por ejemplo 'if (Comparer .Default.Compare (nullableDate, min) <0)'. – Fede

0

Sé que esto no es una respuesta directa a su pregunta, pero podría ayudar a los demás si vienen aquí en busca de algo similar.

Me encontré con este problema hoy al tratar de encontrar solo la fecha máxima de una lista de objetos. A veces no habrá un valor en la fecha para los objetos, así que tuve que descubrir cómo usar un análisis de prueba con mi linq.

de una combinación de lo que Mark utiliza here me ocurrió esto a resolver mi problema

 List<string> stringDates = new List<string>(); 
     stringDates.Add("Not a date"); 
     stringDates.Add("2015-01-01"); 
     stringDates.Add("2015-10-10"); 
     stringDates.Add("2015-9-10"); 
     stringDates.Add("123"); 

     DateTime sapInvoiceDate; 
     DateTime tempDate = DateTime.MinValue; 
     sapInvoiceDate = stringDates.Select(x => DateTime.TryParse(x, out tempDate)).Select(x => tempDate).Max(); 
Cuestiones relacionadas