tags:

views:

76

answers:

3

Please, help minimize the following code: There is a class with dictionary property:

class Foo
{
    public int Field { get; set; }
    public Dictionary<int, bool> dic { get; set; }
}

And a list of Foo instances. I want to get united dictionary from all class instances like that:

...

var items = new List<Foo>
    {
        new Foo {Field = 1, Dic = new Dictionary<int, bool> {{1, true}, {2, false}}},
        new Foo {Field = 2, Dic = new Dictionary<int, bool> {{3, true}, {2, false}}}
    };
    var result = new Dictionary<int, bool>();

    foreach (var dics in items.Select(x => x.Dic))
        foreach (var pair in dics)
            if (!result.ContainsKey(pair.Key))
                result.Add(pair.Key, pair.Value);

    // testing output 
    foreach (var pair in result)
        Console.WriteLine("{0}, {1}", pair.Key, pair.Value);

Is it possible to do this with pure LINQ approach? Thank you in advance!

+2  A: 
var result =
    (from item in items
     from pair in item.Dic
     group pair by pair.Key
     ).ToDictionary(g => g.Key, g => g.First().Value);
Quartermeister
+6  A: 

You can use SelectMany to grab and flatten the inner dictionary elements:

var result = items.SelectMany(f => f.Dic)
                  .GroupBy(pair => pair.Key)
                  .ToDictionary(g => g.Key, g => g.First().Value);

edit: If you're feeling brave, this can be improved even further by picking up the DistinctBy method from Jon Skeet's morelinq project. Essentially, the GroupBy step is actually overkill, since all we really want is the first value for each key. If we select only the pairs with distinct keys, we can avoid the grouping and subsequent First call, like so:

var result = items.SelectMany(f => f.Dic)
                  .DistinctBy(pair => pair.Key)
                  .ToDictionary(pair => pair.Key, pair => pair.Value);
tzaman
Thank you: SelectMany is powerful method I knew nothing about :)
Andrew Florko
i actually had this one typed up, and by the time i got back it was posted>!
Nix
Yes, it's really powerful. Every LINQ function could actually be implemented by SelectMany :)
bsnote
@Andrew - yeah, `SelectMany` is great. I've also just updated my answer to include another very useful method, check it out. :)
tzaman
+1  A: 

I don't know if Distinct is better but it is shorter to write.

var result = items.SelectMany(d => d.Dic)
                  .Distinct()
                  .ToDictionary(p => p.Key, p => p.Value);

But I actually kind of like using foreach for this.

var result = new Dictionary<int, bool>();

foreach (var dic in items.SelectMany(d => d.Dic))
    result[dic.Key] = dic.Value;
Jonas Elfström