2009-10-28 5 views
41

Mam Dictionary<string, string>.Usuń pozycję w słowniku na podstawie wartości

Muszę zajrzeć do tego słownika, aby sprawdzić, czy wartość istnieje w oparciu o dane wejściowe z innego miejsca, a jeśli istnieje, usuń je.

ContainsValue mówi tylko true/false, a nie indeks lub klucz tego elementu.

Pomoc!

Dzięki

EDIT: Wystarczy znaleźć to - co o tym sądzisz?

var key = (from k in dic where string.Compare(k.Value, "two", true) == 
0 select k.Key).FirstOrDefault(); 

EDIT 2: ja też po prostu zapukał ten up, które mogą pracować

foreach (KeyValuePair<string, string> kvp in myDic) 
{ 
    if (myList.Any(x => x.Id == kvp.Value)) 
     myDic.Remove(kvp.Key); 
} 
+0

I myślę, że potrzebujesz BiDictionary. Sprawdź to pytanie: http://stackoverflow.com/questions/255341/getting-key-of-a-generic-dictionary/255638#255638 –

+3

znalazłeś to w ciągu 5 minut? – Xinus

+0

Znaleźliśmy go na innej stronie – Jon

Odpowiedz

101

Czy próbujesz usunąć pojedynczą wartość lub wszystkie pasujące wartości?

Jeśli próbujesz usunąć pojedynczą wartość, w jaki sposób definiujesz wartość, którą chcesz usunąć?

Powód, dla którego nie zwracano klucza podczas sprawdzania wartości, jest taki, że słownik może zawierać wiele kluczy sparowanych z określoną wartością.

Jeśli chcesz usunąć wszystkie wystąpienia dopasowania o tej samej wartości, można to zrobić:

foreach(var item in dic.Where(kvp => kvp.Value == value).ToList()) 
{ 
    dic.Remove(item.Key); 
} 

A jeśli chcesz usunąć pierwsze wystąpienie dopasowanie, można wyszukać na znalezienie pierwszego elementu i po prostu usuń że:

var item = dic.First(kvp => kvp.Value == value); 

dic.Remove(item.Key); 

Uwaga:ToList() połączenie jest konieczne, aby skopiować wartości do nowej kolekcji. Jeśli wywołanie nie zostanie wykonane, pętla będzie modyfikować kolekcję, która jest iterowana, powodując zgłoszenie wyjątku przy następnej próbie iteracji po usunięciu pierwszej wartości.

+7

Pierwszy przykład kodu nie działa, ponieważ nie można modyfikować kolekcji w pętli foreach. –

+0

Anonimowa edycja usunęła niektóre niezbędne kody. Oddam trochę z powrotem. –

+0

+1 za podanie informacji w notatce. – Roger

2

Przelotowe słowniku znaleźć indeks, a następnie wyjąć go.

+0

Jak zauważono w zaakceptowanej odpowiedzi, jeśli usuniesz element słownika podczas przeglądania w słowniku, zostanie zgłoszony błąd, jeśli po usunięciu usunięto wartości ze słownika. – ammills01

6
Dictionary<string, string> source 
// 
//functional programming - do not modify state - only create new state 
Dictionary<string, string> result = source 
    .Where(kvp => string.Compare(kvp.Value, "two", true) != 0) 
    .ToDictionary(kvp => kvp.Key, kvp => kvp.Value) 
// 
// or you could modify state 
List<string> keys = source 
    .Where(kvp => string.Compare(kvp.Value, "two", true) == 0) 
    .Select(kvp => kvp.Key) 
    .ToList(); 

foreach(string theKey in keys) 
{ 
    source.Remove(theKey); 
} 
0

W moim przypadku Używam tego

var key=dict.FirstOrDefault(m => m.Value == s).Key; 
      dict.Remove(key); 
1

Oto sposób można użyć:

public static void RemoveAllByValue<K, V>(this Dictionary<K, V> dictionary, V value) 
    { 
     foreach (var key in dictionary.Where(
       kvp => EqualityComparer<V>.Default.Equals(kvp.Value, value)). 
       Select(x => x.Key).ToArray()) 
      dictionary.Remove(key); 
    } 
0

można użyć następujących jako metodę rozszerzenia

public static void RemoveByValue<T,T1>(this Dictionary<T,T1> src , T1 Value) 
    { 
     foreach (var item in src.Where(kvp => kvp.Value.Equals(Value)).ToList()) 
     { 
      src.Remove(item.Key); 
     } 
    }