Linq中的平均扩展方法为默认值

时间:2011-03-29 02:05:43

标签: c# .net sql linq average

任何人都知道如何设置平均值的默认值?我有这样一条线......

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.我认为这应该是一个扩展方法,我可以指定默认值应该是什么。

4 个答案:

答案 0 :(得分:42)

有:DefaultIfEmpty

我不确定您的DbVersionsDbRatings是什么以及哪些收藏品完全没有项目,但这是个主意:

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

如果您不希望/不能构建ItemValue等于0的默认int,则可以首先投影到var avg = list.Select(item => item.Value).DefaultIfEmpty(0).Average(); 的集合,然后 提供默认值:

{{1}}

答案 1 :(得分:0)

我认为没有办法选择默认值,但这个查询怎么样

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。

答案 2 :(得分:0)

我的建议是创建一个可重用的解决方案,而不是仅针对此问题的解决方案。

设置扩展方法AverageOrDefault,类似于FirstOrDefault。参见extension methods demystified

public static class MyEnumerableExtensions
{
    public static double AverageOrDefault(this IEnumerable<int> source)
    {
        // TODO: decide what to do if source equals null: exception or return default?
        if (source.Any())
            return source.Average();
        else
            return default(int);
    }
}

Enumerable.Average有9个重载,因此您需要为double,int?,decimal等创建一个AverageOrDefault。它们看起来都相似。

用法:

// Get the average order total or default per customer
var averageOrderTotalPerCustomer = myDbContext.Customers
    .GroupJoin(myDbContext.Orders,
    customer => customer.Id,
    order => order.CustomerId,
    (customer, ordersOfThisCustomer) => new
    {
        Id = customer.Id,
        Name  = customer.Name,
        AverageOrder = ordersOfThisCustomer.AverageOrDefault(),
    });

答案 3 :(得分:-2)

我尝试了其中一些答案但最终由于某种原因而获得了更多例外。这最终为我工作。我确信表现很糟糕但我稍后会修改。

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