使用LINQ将Dictionary<int, int?>转换为Dictionary<int, int>,跳过空值。

3

我有下面这个Product类:

public class Product
{
    public string Name { get; set; }
    public float Price { get; set; }     
    public int? CategoryId { get; set; }
}

现在我需要计算每个 CategoryId 中有多少个 Product,并将它们放入一个 Dictionary<int, int> 中。因此:
IQueryable<Product> products = _productServices.GetAll(); //return IQueryable<Product>

Dictionary<int, int> productDict =  products.ToList()
                                            .GroupBy(p => p.CategoryId)
                                            .ToDictionary(pgroup => pgroup.key, pgroup => pgroup.Count());

问题在于我从ToDictionary()中获取了一个Dictionary<int?, int>。即使我通过Where(p => p.CategoryId != null)对空值进行了预过滤,但我并没有改变CategoryId的类型为int。我还尝试创建了一个匿名类型:
products.ToList()
        .GroupBy(p => p.CategoryId)
        .Select(p => new { p.key ?? -1, p.Count() }  
        .ToDictionary(pgroup => pgroup.key, pgroup => pgroup);

但是它会报错:无效的匿名类型成员声明。我也试过去掉ToList(),但没有成功。我在谷歌上搜了一下,没有找到任何人遇到这个问题,虽然我认为这种情况可能经常发生,尤其是在使用EF数据库时。有人有解决方案吗?


尝试使用p.CategoryId.Value(非空)而不是p.CategoryId - user
4个回答

7

这是因为CategoryId是可空的。所以您需要先选择它的Value属性:

products.ToList()
        .Where(p => p.CategoryId.HasValue)
        .Select(p => p.CategoryId.Value)
        .GroupBy(i => i)
        .ToDictionary(g => g.Key, g => g.Count());

2
+1 是为了包括“为什么”它不起作用的原因,而不是简单地绕过它。 - J. Steen

6

只需简单使用

products.ToList()
    .GroupBy(p => p.CategoryId)
    .Where(pgroup => pgroup.Key.HasValue)
    .ToDictionary(pgroup => pgroup.Key.Value, pgroup => pgroup.Count());

5

这个怎么样?

.ToDictionary(pgroup => pgroup.Key ?? -1, pgroup => pgroup.Count());

关于您在匿名类型上的语法错误,正确的语法如下:

.Select(p => new { Key = p.Key ?? -1, Count = p.Count() })

细节问题;OP明确表示“跳过空值”-尝试包含它们是很好的,但你需要询问是否-1已经是一个有效值。 - Marc Gravell

0

你需要过滤掉空值,然后使用 int?.Value 属性作为分组键:

products.ToList()
        .Where(p => p.CategoryId.HasValue)
        .GroupBy(p => p.CategoryId.Value)
        .ToDictionary(pgroup => pgroup.key, pgroup => pgroup.Count());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接