c# groupby list - Average extension method in Linq for default value

2 Answers

There is: DefaultIfEmpty.

I 'm not sure about what your DbVersions and DbRatings are and which collection exactly has zero items, but this is the idea:

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

Update: (repeating what's said in the comments below to increase visibility)

If you find yourself needing to use DefaultIfEmpty on a collection of class type, remember that you can change the LINQ query to project before aggregating. For example:

class Item
    public int Value { get; set; }

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

If you don't want to/can not construct a default Item with Value equal to 0, you can project to a collection of ints first and then supply a default:

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

Anyone know how I can set a default value for an average? I have a line like this...

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();

which throws an error becase I have no ratings yet. If I have none I want the average to default to 0. I was thinking this should be an extension method where I could specify what the default value should be.

I tried some of those answers but ended up getting more exceptions for one reason or another. this ended up working for me. I am sure the performance is aweful but I will revise later.

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();