2010-08-02 4 views
2

J'ai deux dictionnaires commeComparaison et fusion de dictionnaires en utilisant LINQ en C#

Dictionary<String,List<String>> DictOne=new Dictionary<String,List<String>>() 
    Dictionary<String,List<String>> DictTwo=new Dictionary<String,List<String>>() 

DictOne 


KeyOne  "A" 
      "B" 

KeyTwo  "C" 
      "D" 

KeyThree "X" 
      "Y" 



DictTwo 

Key1  "X" 
      "Z" 
      "Y" 

Key2  "A" 


Key3  "C" 
     "D" 

Key4  "M" 
     "N" 

i besoin de comparer et de fusionner les deux dictonaries quelle que soit la clé et d'ajouter les données au troisième dictionnaire

Dictionary<String,List<String>> DictThree=new Dictionary<String,List<String>>() 

Ainsi, le troisième dictionnaire contiendra

DictThree 

KeyOne "A" 
     "B" 

KeyTwo "C" 
     "D" 

KeyThree "X" 
     "Y" 
     "Z" 

Key4  "M" 
     "N" 

maintenant, je suis itérer les deux dictionar s

Maintenant, je suis en utilisant comme

d'abord je vais prendre la première liste dans la DictOne et la recherche ensuite si les éléments de la liste existent dans une liste dans DictTwo le cas échéant effectuer une opération d'union, puis ajoutez la liste résultante dans le troisième dictionnaire avec la clé any (clé dans DictOne ou dans DictTwo) Si la liste n'existe pas alors ajouter la liste avec la clé dans le troisième dictionnaire. Le même se produira pour toutes les listes dans DictOne Et DictTwo

Est-il possible de le faire en utilisant LINQ

Merci à l'avance

Répondre

2

Ouf! Tout un défi. Fondamentalement, ce fait qu'ils sont des dictionnaires est complètement hors de propos, vous avez juste besoin de la partie Dictionary<,>.Values de chaque dictionnaire, donc je vais juste utiliser un tableau de tableaux de chaînes (string[][]) pour cet exemple.

var group1 = new string[][] { new[] { "A", "B" }, new[] { "C", "D" }, new[] { "X", "Y" } }; 
var group2 = new string[][] { new[] { "X", "Y", "Z" }, new[] { "A" }, new[] { "C", "D" }, new[] { "M", "N" } }; 

// For each array in group1, check if it has matching array in group2, if 
// it does, merge, otherwise just take the array as is. 
var group1Join = from g1 in group1 
       let match = group2.SingleOrDefault(g2 => g1.Intersect(g2).Any()) 
       select match != null ? g1.Union(match) : g1; 

// Take all the group2 arrays that don't have a matching array in group1 and 
// thus were ignored in the first query. 
var group2Leftovers = from IEnumerable<string> g2 in group2 
         where !group1.Any(g1 => g2.Intersect(g1).Any()) 
         select g2; 

var all = group1Join.Concat(group2Leftovers); 

EDIT: code corrigé pour travailler en C# 3.0, et ne pas compter sur le soutien de covariance de C# 4.0.

+0

Je n'ai aucune idée de la raison pour laquelle cette réponse a été rejetée, car elle semble répondre correctement à la question un peu floue. –

+0

Encore plus intéressant est le fait que cette question n'a pas moins de 4 downvotes sur quatre réponses différentes, sans un seul commentaire dans l'un d'eux expliquant la raison. –

+0

@ Allon Guralnek: toutes les réponses ne font que concaténer les deux dictionnaires sauf le vôtre. Et dans votre réponse, IEnumerable ne peut pas être converti en IEnumerable > –

-1

Vous pouvez le faire:

Dictionary<String, List<String>> DictThree = DictOne.Concat(DictTwo); 

Ou cette , si vous avez besoin de le garder comme un dictionnaire:

Dictionary<String, List<String>> DictThree = DictOne.Concat(DictTwo).ToDictionary(x => x.Key); 
-1

Vous pouvez utiliser cette approche ch:

var dict3 = DictOne 
    .Concat(DictTwo) 
    .GroupBy(x => x.Key) 
    .ToDictionary(x => x.Key, x => x.SelectMany(y => y.Value).ToList()); 

Bien sûr, si vous voulez utiliser votre propre comparaison d'égalité, vous pouvez servir IEqualityComparer à la méthode GroupBy comme second argument.

-1

Si ce que vous voulez est que vous fusionnez toutes les entrées de chaque liste par clé, vous pouvez le faire comme ceci:

var dictThree = (from kv in dictOne.Concat(dictTwo) 
        group kv.Value by kv.Key) 
    .ToDictionary(k => k.Key, v => v.SelectMany(l => l).Distinct().ToList()); 

Cela donnera des chaînes distinctes dans chaque liste par clé.

+0

Il s'agit simplement de concaténer les deux dictionnaires. J'ai besoin de concaténer basé sur la valeur pas sur la clé –

+0

Eh bien, la question était un peu sur le côté cryptique, n'est ce pas? ;-) –