Средний метод расширения в Linq для значения по умолчанию
Кто-нибудь знает, как я могу установить значение по умолчанию для среднего? У меня есть такая строка...
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();
который выдает ошибку, потому что у меня нет оценок. Если у меня нет ни одного, я хочу, чтобы среднее значение по умолчанию равнялось 0. Я думал, что это должен быть метод расширения, где я могу указать, какое значение по умолчанию должно быть.
Ответы
Ответ 1
Я попробовал некоторые из этих ответов, но в итоге получал больше исключений по той или иной причине. это закончило работать для меня. Я уверен, что производительность впечатляет, но я буду пересматривать позже.
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();
Ответ 2
Существует: DefaultIfEmpty
.
Я не уверен, что ваши DbVersions
и DbRatings
есть, и какая коллекция точно имеет нулевые элементы, но это идея:
var emptyCollection = new List<int>();
var average = emptyCollection.DefaultIfEmpty(0).Average();
Обновление: (повторяя сказанное в комментариях ниже, чтобы увеличить видимость)
Если вам нужно использовать DefaultIfEmpty
в коллекции типа класса, помните, что вы можете сменить запрос LINQ на проект до агрегации. Например:
class Item
{
public int Value { get; set; }
}
var list = new List<Item>();
var avg = list.Average(item => item.Value);
Если вы не хотите/не можете создать по умолчанию Item
с Value
равным 0, сначала вы можете выполнить проект в int
, а затем указать по умолчанию:
var avg = list.Select(item => item.Value).DefaultIfEmpty(0).Average();
Ответ 3
Я не думаю, что есть способ выбрать значение по умолчанию, но как насчет этого запроса
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();
По существу то же самое, что и у вас, но мы сначала спросим, есть ли какие-либо оценки перед их усреднением. Если нет, мы возвращаем 0.