2009-09-22 12 views
17

Comment puis-je créer un dictionnaire sans doublon d'un dictionnaire pouvant contenir des valeurs en double?C#: Supprimer les valeurs en double du dictionnaire?

IDictionary<string, string> myDict = new Dictionary<string, string>(); 

myDict.Add("1", "blue"); 
myDict.Add("2", "blue"); 
myDict.Add("3", "red"); 
myDict.Add("4", "green"); 


uniqueValueDict = myDict.??? 

Edit:

-I ne se soucient pas quelle clé est conservée. - Y a-t-il quelque chose qui utilise l'opération Distinct()?

+6

Quelle clé souhaitez-vous conserver? '" 1 "' '2" 'ou aucun? – dtb

+0

[http://www.codeproject.com/KB/linq/Unique.aspx](http://www.codeproject.com/KB/linq/Unique.aspx) –

+0

Je pense que vous devez donner plus d'informations sur le comportement de la fonction unique. Pour le bleu, quelle clé devrait-il garder, 1 ou 2? – Tesserex

Répondre

43

Que voulez-vous faire avec les doublons? Si cela ne vous dérange pas quelle clé vous perdez, juste construire un autre dictionnaire comme celui-ci:

IDictionary<string, string> myDict = new Dictionary<string, string>(); 

myDict.Add("1", "blue"); 
myDict.Add("2", "blue"); 
myDict.Add("3", "red"); 
myDict.Add("4", "green"); 

HashSet<string> knownValues = new HashSet<string>(); 
Dictionary<string, string> uniqueValues = new Dictionary<string, string>(); 

foreach (var pair in myDict) 
{ 
    if (knownValues.Add(pair.Value)) 
    { 
     uniqueValues.Add(pair.Key, pair.Value); 
    } 
} 

qui suppose que vous utilisez .NET 3.5, il est vrai. Faites-moi savoir si vous avez besoin d'une solution .NET 2.0.

est ici une solution basée LINQ que je trouve agréablement compact ...

var uniqueValues = myDict.GroupBy(pair => pair.Value) 
         .Select(group => group.First()) 
         .ToDictionary(pair => pair.Key, pair => pair.Value); 
+0

Wow Jon, vous avez presque cassé la marque 100K :-) –

+10

Little sait-il après 100K il boucle à 0, ruuhaha – SwDevMan81

+0

Merci. La solution linq est ce que je cherchais. Curieux pourriez-vous en quelque sorte utiliser la méthode d'extension Distinct? – User

1
foreach (var key in mydict.Keys) 
    tempdict[mydict[key]] = key; 
foreach (var value in tempdict.Keys) 
    uniquedict[tempdict[value]] = value; 
8

La solution force brute serait quelque chose comme le

var result = dictionary 
    .GroupBy(kvp => kvp.Value) 
    .ToDictionary(grp => grp.First().Value, grp.Key) 

supposant que vous suivant n » Il faut vraiment se préoccuper de la clé utilisée pour représenter un groupe de doublons et il est acceptable de reconstruire le dictionnaire.

+0

J'ai essayé d'imaginer une solution de type linq mais je n'avais pas de VS à portée de main. +1 pour la matérialisation de cette approche ;-) – queen3

+0

Je ne suis pas sûr si elle compile même ... juste aller au VS et le tester ... –

+0

N'a pas compilé parce que j'ai manqué .Value après l'appel First(), mais l'a réparé. –

1
Dictionary<string, string> test = new Dictionary<string,string>(); 
test.Add("1", "blue"); 
test.Add("2", "blue"); 
test.Add("3", "green"); 
test.Add("4", "red"); 
Dictionary<string, string> test2 = new Dictionary<string, string>(); 
foreach (KeyValuePair<string, string> entry in test) 
{ 
    if (!test2.ContainsValue(entry.Value)) 
     test2.Add(entry.Key, entry.Value); 
} 
3

Jon m'a battu à la solution .NET 3.5, mais cela devrait fonctionner si vous avez besoin d'une solution .NET 2.0:

 List<string> vals = new List<string>(); 
     Dictionary<string, string> newDict = new Dictionary<string, string>(); 
     foreach (KeyValuePair<string, string> item in myDict) 
     { 
      if (!vals.Contains(item.Value)) 
      { 
       newDict.Add(item.Key, item.Value); 
       vals.Add(item.Value); 
      } 
     } 
0

En plus de la réponse de Jon Skeet, si votre valeur est un objet stagiaire, vous pouvez utiliser:

var uniqueValues = myDict.GroupBy(pair => pair.Value.Property) 
        .Select(group => group.First()) 
        .ToDictionary(pair => pair.Key, pair => pair.Value); 

de cette façon, vous allez supprimer le double que sur une propriété de l'objet

1

Voilà comment je l'ai fait:

   dictionary.add(control, "string1"); 
       dictionary.add(control, "string1"); 
       dictionary.add(control, "string2"); 
       int x = 0; 
     for (int i = 0; i < dictionary.Count; i++) 
     {   
      if (dictionary.ElementAt(i).Value == valu) 
      { 
       x++; 
      } 
      if (x > 1) 
      { 
       dictionary.Remove(control); 
      } 
     } 
0

Juste une note à ceux qui utilisent l'API Revit, ceci est une méthode qui fonctionne pour moi en supprimant les doublons, lorsque vous ne pouvez pas utiliser dire wallType comme type d'objet et à la place besoin de tirer parti des éléments bruts. c'est un mec beaut.

//Add Pair.value to known values HashSet 
       HashSet<string> knownValues = new HashSet<string>(); 

       Dictionary<Wall, string> uniqueValues = new Dictionary<Wall, string>(); 

       foreach (var pair in wall_Dict) 
       { 
        if (knownValues.Add(pair.Value)) 
        { 
         uniqueValues.Add(pair.Key, pair.Value); 
        } 
       } 
Questions connexes