2009-09-22 67 views
17

¿Cómo puedo crear un diccionario sin valores duplicados de un diccionario que pueda tener valores duplicados?C#: ¿Eliminar valores duplicados del diccionario?

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.??? 

Editar:

-No me importa qué tecla se mantiene. - ¿Hay algo utilizando la operación Distinct()?

+6

¿Qué tecla quieres conservar? '" 1 "', '" 2 "', o ninguno? – dtb

+0

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

+0

Creo que debe proporcionar más información sobre la comportamiento de la función de creación única. Para azul, ¿qué tecla debería conservar, 1 o 2? – Tesserex

Respuesta

43

¿Qué desea hacer con los duplicados? Si no le importa qué tecla se pierde, simplemente construir otro diccionario de la siguiente manera:

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

que asume que está utilizando .NET 3.5, es cierto. Avíseme si necesita una solución .NET 2.0.

Aquí es una solución basada en LINQ que encuentro gratamente compacta ...

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

Wow Jon, casi rompiste la marca de los 100K :-) –

+10

Poco sabe después de 100K vuelve a 0, ruuhaha – SwDevMan81

+0

Gracias. La solución linq es lo que estaba buscando. ¿Curioso podría de alguna manera usar el método de extensión 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 solución de fuerza bruta sería algo así como lo siguiente

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

suponiendo que usted don' realmente me importa la clave utilizada para representar un grupo de duplicados y es aceptable reconstruir el diccionario.

+0

Traté de imaginar una solución similar a linq pero no tenía VS en la punta de mis dedos. +1 para materializar este enfoque ;-) – queen3

+0

No estoy seguro si incluso se compila ... simplemente voy a disparar VS y probarlo ... –

+0

No compilé porque perdí .Value después de la llamada a First(), pero lo solucionó –

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 me pegaba a la solución .NET 3.5, pero esto debería funcionar si necesita una solución .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

Además de la respuesta de Jon Skeet, si su valor es un objeto interno que puede utilizar:

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

de esta manera se retire el duplicado sólo en una propiedad del objeto

1

Esta es la forma en que lo hice:

   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

Sólo una nota al pie de los que utilizan la API de Revit, este es un método que funciona para mí en la eliminación de elementos duplicados, cuando no se puede utilizar decir wallType como su tipo de objeto y en su lugar necesita aprovechar elementos crudos. es un beaut mate

//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); 
        } 
       } 
Cuestiones relacionadas