2009-06-30 8 views
0

Je suis un grand noob avec Linq et j'essaie d'apprendre, mais je frappe un point bloquant ici. Je ont une structure de type:Linq question

Dictionary<MyType, List<MyObj>> 

Et je voudrais interroger avec Linq cette structure pour extraire toutes les instances de MyObj qui apparaissent dans plus d'une liste dans le dictionnaire.

À quoi ressemblerait une telle requête?

Merci.

Répondre

3
from myObjectList in myObjectDictionary.Values 
from myObject in myObjectList.Distinct() 
group myObject by myObject into myObjectGroup 
where myObjectGroup.Skip(1).Any() 
select myObjectGroup.Key 

Le Distinct() sur chaque liste assure MyObj cas qui se répètent uniquement dans le même liste ne sont pas signalés.

1

Vous pouvez faire quelque chose comme ceci:

var multipleObjs = 
    MyObjDictionary.Values // Aggrigate all the List<MyObj> values into a single list 
     .SelectMany(list => list) // Aggrigate all the MyObjs from each List<MyObj> into a single IEnumerable 
     .GroupBy(obj => obj) // Group by the Obj itself (Or an ID or unique property on them if it exists) 
     .Where(group => group.Count() >= 2) // Filter out any group with less then 2 objects 
     .Select(group => group.Key); // Re-Select the objects using the key. 

Modifier
je réalisais que cela pourrait aussi être lu diffrently, de sorte qu'il n'a pas d'importance si le MyObj se produit plusieurs fois dans la même liste , mais seulement si cela se produit plusieurs fois dans diffrent listes. Dans ce cas, quand nous initally aggrigating les listes de MYOBJS nous pouvons sélectionner des valeurs Distinct, ou utiliser une requête légèrement diffrent:

var multipleObjs = 
    MyObjDictionary.Values // Aggrigate all the List<MyObj> values into a single list 
     .SelectMany(v => v.Distinct()) // Aggrigate all distinct MyObjs from each List<MyObj> into a single IEnumerable 
     .GroupBy(obj => obj) // Group by the Obj itself (Or an ID or unique property on them if it exists) 
     .Where(group => group.Count() >= 2) // Filter out any group with less then 2 objects 
     .Select(group => group.Key); // Re-Select the objects using the key. 


var multipleObjs = 
     MyObjDictionary.SelectMany(kvp => // Select from all the KeyValuePairs 
      kvp.Value.Where(obj => 
       MyObjDictionary.Any(kvp2 => // Where any of the KeyValuePairs 
        (kvp.Key != kvp2.Key) // Is Not the current KeyValuePair 
        && kvp.Value.Contains(obj)))); // And also contains the same MyObj. 
+2

Just SelectMany (v => v) devrait faire? (pas besoin de v.Select (obj => obj)) –

+0

Vous avez raison. En général, j'écris explicitement ce que je sélectionne dans des requêtes plus complexes car il m'est plus facile de suivre ce qui se passe et de l'optimiser ensuite, mais j'ai oublié dans ce cas. C'est réglé maintenant de toute façon. – rmoore

+0

Count() énumérera chaque groupe dans son intégralité. Utiliser Skip (1) .Any() est plus efficace. –