2010-06-30 3 views
3

S'il vous plaît, aider à minimiser le code suivant: Il y a une classe propriété dictionnaire:Expression Linq. Aide mimize Code

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

Et la liste des instances Foo. Je veux obtenir le dictionnaire uni de toutes les instances de classe comme ça:

...

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

Est-il possible de le faire avec l'approche pure LINQ? Merci d'avance!

Répondre

6

Vous pouvez utiliser SelectMany pour saisir et aplatir les éléments du dictionnaire interne:

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

modifier: Si vous vous sentez courageux, cela peut être encore améliorée en ramassant la méthode DistinctBy du projet morelinq de Jon Skeet. Essentiellement, l'étape GroupBy est réellement excessive, puisque tout ce que nous voulons vraiment, c'est la première valeur pour chaque clé. Si nous ne sélectionnons que les paires avec des clés distinctes, nous pouvons éviter le regroupement et après First appel, comme ceci:

var result = items.SelectMany(f => f.Dic) 
        .DistinctBy(pair => pair.Key) 
        .ToDictionary(pair => pair.Key, pair => pair.Value); 
+0

Merci: SelectMany est puissante méthode je ne savais rien :) –

+0

j'avais fait celui tapé, et au moment où je suis rentré, il a été affiché>! – Nix

+0

Oui, c'est vraiment puissant. Chaque fonction LINQ pourrait effectivement être implémentée par SelectMany :) –

2
var result = 
    (from item in items 
    from pair in item.Dic 
    group pair by pair.Key 
    ).ToDictionary(g => g.Key, g => g.First().Value); 
1

Je ne sais pas si Distinct est mieux, mais il est plus court à écrire.

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

Mais je fait un peu comme en utilisant foreach pour cela.

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

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