2009-09-22 11 views
17

Jak mogę utworzyć słownik bez powielonych wartości ze słownika, który może mieć zduplikowane wartości?C#: Usunąć zduplikowane wartości ze słownika?

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 nie obchodzi który klucz jest przechowywany. - Czy jest coś, co używa funkcji Distinct()?

+6

Który klucz chcesz zachować? '" 1 "', '" 2 "' lub brak? – dtb

+0

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

+0

Myślę, że trzeba podać więcej informacji na temat zachowanie funkcji tworzenia niepowtarzalnych elementów. Dla niebieskiego, który klucz powinien zachować, 1 lub 2? – Tesserex

Odpowiedz

43

Co chcesz zrobić z duplikatami? Jeśli nie masz nic przeciwko utraconemu kluczowi, po prostu zbuduj inny słownik taki jak ten:

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

Zakładamy, że korzystasz z .NET 3.5, co prawda. Daj mi znać, jeśli potrzebujesz rozwiązania .NET 2.0.

Oto rozwiązanie oparte na LINQ, które uważam za mile kompaktowy ...

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

Wow Jon, prawie złamałeś znak 100K :-) –

+10

Nie wie on po 100K pętli z powrotem do 0, ruuhaha – SwDevMan81

+0

Dzięki. Rozwiązanie linq jest tym, czego szukałem. Ciekawy czy mógłbyś w jakiś sposób użyć metody Distinct extension? – User

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

Rozwiązanie brute-force byłoby coś jak na poniższym

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

zakładając, że don” t naprawdę dba o klucz używany do reprezentowania grupy duplikatów i dopuszczalne jest odbudowanie słownika.

+0

Próbowałem sobie wyobrazić rozwiązanie podobne do linq, ale nie miałem VS na wyciągnięcie ręki. +1 za zmaterializowanie tego podejścia ;-) – queen3

+0

Nie jestem pewien, czy to nawet kompiluje ... po prostu odpalam VS i testuję to ... –

+0

Nie skompilowałem, ponieważ przegapiłem. Wartość po pierwszym() wywołaniu, ale naprawił to. –

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 pokazał mi do roztworu .NET 3.5, ale to powinno działać, jeśli potrzebujesz .NET 2.0 rozwiązanie:

 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

Oprócz odpowiedzi Jon Skeet, jeśli wartość jest przedmiotem stażysta można użyć:

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

ten sposób można usunąć duplikat tylko na jednej właściwości obiektu

1

To jest, jak to zrobiłem:

   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

Tylko przypis do tych używając API Revit, jest to jedna metoda, która działa na mnie w usuwaniu zduplikowanych elementów, gdy nie można użyć powiedzieć wallType jako typ obiektu i zamiast tego trzeba wykorzystać elementy surowe. to piękny partner.

//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); 
        } 
       } 
Powiązane problemy