2010-09-28 2 views
2

Très souvent, j'utilise le type Dictionary<TKey, TValue> pour stocker ehh ... les types de valeurs de dictionnaire, par ex. Key = 1, Value ="Canada". Mais dans de nombreux cas, les valeurs des données du dictionnaire sont également uniques, tout comme les clés. Et je trouve que pour le type Dictionary<TKey, TValue>, il n'est pas très pratique d'obtenir la valeur de la clé en fonction de la valeur.Classe .NET pour trouver rapidement Valeur basée sur la clé et vice versa

Ma question est, quelle classe dans .NET, convient dans ce scénario? Trouvez rapidement la valeur basée sur la clé et vice versa.

Répondre

4

Ceci est assez trivial LINQ:

int key = new Dictionary<int,string>().Where((kv)=>kv.Value == "SomeValue").Select(kv=>kv.Key).FirstOrDefault(); 

Et une méthode d'extension si vous avez envie:

static class DictionaryExtensions { 
    public static bool TryFindByValue<TKey, TValue>(this IDictionary<TKey, TValue> dict, TValue value, out TKey key) { 
     var keys = dict.Where((kv) => kv.Value.Equals(value)).Select(kv => kv.Key); 
     bool retValue = keys.Any(); 
     key = keys.FirstOrDefault(); 
     return retValue; 
    } 
} 

Qu'est-ce que vous pouvez aussi faire est de mettre en œuvre IDictionary, déléguer à deux objets Dictionary (un pour le mappage de valeur de clé et un pour le mappage de clé de valeur) pour sauvegarder la banque et avoir une contrainte sur Add que les valeurs doivent être uniques. De cette façon, vous avez la garantie qu'il y aura au plus une entrée avec une valeur particulière. EDIT L'utilisation de deux dictionnaires améliorera le temps d'accès (merci @SamStephens) car les clés et les valeurs seront stockées dans une table de hachage ordonnée.

+0

La même chose que '.FirstOrDefault (p => Val.par == "SomeValue") clé;.' Mais mon est plutôt plus rapide. (une vérification nulle supplémentaire est requise dans les deux cas) – abatishchev

+0

Déréférencement Clé dans '.FirstOrDefault (p => p.Value ==" SomeValue "). Key;' se bloquera s'il n'y a pas de paire clé/valeur satisfaisant la condition. Il est plus sûr de 'FirstOrDefault()' à la fin de la chaîne courante. –

+0

N'a pas la vitesse d'accès à un dictionnaire par clé – SamStephens

2

Ne pensez pas qu'il y a quelque chose qui est livré avec .NET. Il y a probablement une classe de 3ème partie. Mais vous pouvez très facilement créer votre propre classe, qui contient deux dictionnaires, l'un avec les clés et les valeurs inversées.

0

Vous pouvez mettre en miroir le dictionnaire en utilisant deux dictionnaires, mais cela ne fonctionnera que si la collection de valeurs est également unique, ce qui semble étrange et improbable. Sinon, vous devrez interroger la propriété Values ​​pour la bonne.

(
from x in dict.Values 
where x.Prop == "someValue" 
select x 
) 
.FirstOrDefault() 

OU, simplement

dict.Values.FirstOrDefault(x => x.Prop == "someValue"); 
1

(nécessite .NET 4.0)

var list = new List<Tuple<int, string>> 
{ 
new Tuple<int, string>(1, "Canada"), 
new Tuple<int, string>(2, "USA") 
}; 

var i = list.FirstOrDefault(t => t.Item1 == 1); 
var j = list.FirstOrDefault(t => t.Item2 == "USA"); 
+0

Souhaite que je pourrais donner +2 pour la mention des tuples – johnc

+0

N'a pas la vitesse d'accéder à un dictionnaire par clé – SamStephens