Linq 按 Sum 分组,但如果 sum 为 null,则 return 0

Linq group by Sum but also return 0 if sum is null

我有以下类型:

class ItemTotals
{
    public decimal Total { get; set; }
    public string ItemType { get; set; }
}

我正在使用以下方法获取每个 ItemType 的总数:

        var items = new List<ItemTotals>
        {
            new ItemTotals
            {
                Total = 10,
                ItemType = "X"
            },
            new ItemTotals
            {
                Total = 10,
                ItemType = "X"
            },
            new ItemTotals
            {
                Total = -5,
                ItemType = "Y"
            },
            new ItemTotals
            {
                Total = -20,
                ItemType = "Y"
            }
        };


        List<ItemTotals> query = items.GroupBy(x => x.ItemType)
                                      .Select(x => new ItemTotals
                                      {
                                          ItemType = x.Key,
                                          Total = x.Sum(z => z.Total)
                                      }).ToList();

X 的总计为 20,Y 的总计为 -25。但是假设如果所有的项目类型都是 X,那么我只得到一个结果,X 的总计为 -5,而 Y 的总计没有结果,我想要的是 0,这可能吗?

谢谢

在列表初始化后添加这些行

items.Add(new ItemTotals {Total = 0, ItemType = "X"});
items.Add(new ItemTotals {Total = 0, ItemType = "Y"});

您可以找到列表中未包含的类型并将它们添加到循环中:

List<string> itemTypes = new List<string>() {"X", "Y", "Z"};

foreach(var type in itemTypes)
{
     if(!items.Any(x => x.ItemType == type)
           items.Add(new ItemTotals() {ItemType = type, Total = 0})
}

List<ItemTotals> query = items.GroupBy(x => x.ItemType)....

一种方法是将已知名称的集合与零配对添加到集合中,如下所示:

var[] names = new {"X", "Y", "Z"};
List<ItemTotals> query = items
    .Concat(names.Select(n => new ItemTotals {Total = 0, ItemType = n}))
    .GroupBy(x => x.ItemType)
    ... // And so on

Concat 确保每个名称至少有一个项目,并且该项目的总数为零。在某种程度上,添加的项目用作 "sentinels":如果项目名称存在,它们没有区别,但如果名称不存在,它们确保将零行添加到结果。