Aquí es una aplicación completa y genérica de la mediana que maneja adecuadamente colecciones vacías y tipos anulables. Es LINQ-amigable en el estilo de Enumerable.Average, por ejemplo:
double? medianAge = people.Median(p => p.Age);
Esta implementación devuelve un valor nulo cuando no hay valores no nulos en la colección, pero si no te gusta el tipo de retorno anulable , puedes cambiarlo fácilmente para lanzar una excepción.
public static double? Median<TColl, TValue>(
this IEnumerable<TColl> source,
Func<TColl, TValue> selector)
{
return source.Select<TColl, TValue>(selector).Median();
}
public static double? Median<T>(
this IEnumerable<T> source)
{
if(Nullable.GetUnderlyingType(typeof(T)) != null)
source = source.Where(x => x != null);
int count = source.Count();
if(count == 0)
return null;
source = source.OrderBy(n => n);
int midpoint = count/2;
if(count % 2 == 0)
return (Convert.ToDouble(source.ElementAt(midpoint - 1)) + Convert.ToDouble(source.ElementAt(midpoint)))/2.0;
else
return Convert.ToDouble(source.ElementAt(midpoint));
}
tener cuidado si los datos están viniendo de una base de datos, como LINQ puede leer los datos más de una vez, sin embargo, en su caso LINQ debería ser una buena herramienta a medida que parecen tener su colección en la memoria RAM. –