CiccioMiami
CiccioMiami

Reputation: 8266

Convert Dictionary<int, int?> to Dictionary<int, int> by skipping null values with LINQ

I have the following Product class:

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

Now I have to count how many Product I have for each CategoryId and place them in a Dictionary<int, int>. Therefore:

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

The problem is that I obtain a Dictionary<int?, int> from the ToDictionary(). Even if I pre-filter the null values by placing Where(p => p.CategoryId != null) I do not change the type of CategoryId to int. I also tried to create and anonymous type:

products.ToList()
        .GroupBy(p => p.CategoryId)
        .Select(p => new { p.key ?? -1, p.Count() }  
        .ToDictionary(pgroup => pgroup.key, pgroup => pgroup);

But it gives an Invalid anonymous type member declarator error. I also tried to remove the ToList() but no luck. I google it a bit and I haven't found anybody having this issue, although I think this situation might be frequent, especially when working with EF and databases. Anybody has a solution?

Upvotes: 3

Views: 1797

Answers (4)

Tim Schmelter
Tim Schmelter

Reputation: 460238

That's because CategoryId is a nullable. So you need to select it's Value property first:

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

Upvotes: 7

Andrew Cooper
Andrew Cooper

Reputation: 32596

You need to filter out the null values, and then use the .Value property of the int? as the grouping key:

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

Upvotes: 0

Rawling
Rawling

Reputation: 50174

Simply use

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

Upvotes: 6

Thomas Levesque
Thomas Levesque

Reputation: 292635

How about this?

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

And regarding your syntax error with the anonymous type, the correct syntax is as follows:

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

Upvotes: 5

Related Questions