2011-03-29 18 views
11

¿Alguien sabe cómo puedo establecer un valor predeterminado para un promedio? Tengo una línea como esta ...Método de extensión promedio en Linq para el valor predeterminado

dbPlugins = (from p in dbPlugins 
       select new { Plugin = p, AvgScore = p.DbVersions.Average(x => x.DbRatings.Average(y => y.Score)) }) 
      .OrderByDescending(x => x.AvgScore) 
      .Select(x => x.Plugin).ToList(); 

que arroja un error porque todavía no tengo calificaciones. Si no tengo ninguno, quiero que el promedio sea predeterminado a 0. Estaba pensando que este debería ser un método de extensión en el que podría especificar cuál debería ser el valor predeterminado.

Respuesta

-1

Intenté algunas de esas respuestas, pero terminé obteniendo más excepciones por una razón u otra. esto terminó trabajando para mí. Estoy seguro de que el rendimiento es horrible, pero lo revisaré más tarde.

var q1 = from v in db.DbVersions select new { VersionId = v.Id, AvgScore = v.DbRatings.Average(x => x.Score) as Nullable<double> }; 
var q2 = from p in dbPlugins select new { Plugin = p, AvgScore = q1.Where(x => p.DbVersions.Select(y => y.Id).Contains(x.VersionId)).Average(x => x.AvgScore) as Nullable<double> }; 
dbPlugins = q2.OrderByDescending(x => x.AvgScore).Select(x => x.Plugin).ToList(); 
32

Hay DefaultIfEmpty.

No estoy seguro de lo que su DbVersions y DbRatings son y qué colección exactamente tiene cero elementos, pero esta es la idea:

var emptyCollection = new List<int>(); 
var average = emptyCollection.DefaultIfEmpty(0).Average(); 

Actualización: (repitiendo lo que se dijo en los comentarios a continuación a aumento de la visibilidad)

Si ves que necesitas para usar DefaultIfEmpty en una colección de tipo de clase, recuerde que usted puede cambiar la consulta LINQ para proyectar antes de agregación. Por ejemplo:

class Item 
{ 
    public int Value { get; set; } 
} 

var list = new List<Item>(); 
var avg = list.Average(item => item.Value); 

Si no quiere/no se puede construir un defecto Item con Value igual a 0, se puede proyectar a una colección de int s primero y luego suministrar un defecto:

var avg = list.Select(item => item.Value).DefaultIfEmpty(0).Average(); 
+0

@Jon: Pero volviste al principio ahora, 'x.DbRatings' puede ser nulo aquí. 'p.DbVersions.Select (x => x.DbRatings) .DefaultIfEmpty (defaultRatings)', debe especificar '' DefaultRatings', no es simplemente un número. –

0

no creo que haya una manera de seleccionar por defecto, pero ¿qué hay de esta consulta

dbPlugins = (from p in dbPlugins 
      select new { 
       Plugin = p, AvgScore = 
        p.DbVersions.Any(x => x.DbRatings) ? 
         p.DbVersions.Average(x => x.DbRatings.Average(y => y.Score)) : 0 }) 
      .OrderByDescending(x => x.AvgScore) 
      .Select(x => x.Plugin).ToList(); 

Esencialmente el mismo que el suyo, pero primero le preguntamos si hay calificaciones antes de promediarlas. Si no, devolvemos 0.

Cuestiones relacionadas