web-dev-qa-db-fra.com

Obtention d'un KeyValuePair <> directement à partir d'un dictionnaire <>

J'ai System.Collections.Generic.Dictionary<A, B> dict Où A et B sont des classes et une instance A a (Où dict.ContainsKey(a) est vraie).

Est-il possible d'obtenir le KeyValuePair contenant a directement à partir du dictionnaire?
Ou dois-je créer un nouveau KeyValuePair: new KeyValuePair<A, B>(a, dict[a])?

34
user200783

Vous devez créer un nouveau KeyValuePair1 - mais gardez à l'esprit que KVP est de toute façon un type de valeur (une structure), donc ce n'est pas comme si vous introduisiez une nouvelle inefficacité en faisant cela. Toute méthode renvoyant un KVP créerait de toute façon une copie - vous créez simplement l'instance directement.

Vous pouvez toujours ajouter une méthode d'extension à IDictionary<TKey, TValue> si vous vouliez:

public static KeyValuePair<TKey, TValue> GetEntry<TKey, TValue>
    (this IDictionary<TKey, TValue> dictionary,
     TKey key)
{
    return new KeyValuePair<TKey, TValue>(key, dictionary[key]);
}

Comme indiqué dans les commentaires, il est tout à fait possible que la clé qui est stockée dans le dictionnaire ne soit pas la même que celle fournie, juste sémantiquement égale - par certaines sémantiques qui pourraient être personnalisées par un IEqualityComparer (comme avec un dictionnaire qui ne respecte pas la casse, par exemple.) Dans ce cas, le code ci-dessus ne retournerait pas l'entrée réelle dans le dictionnaire, mais une entrée avec la clé que vous avez fournie pour la recherche. Malheureusement, il n'existe aucun moyen efficace de trouver la clé d'origine - vous devez parcourir le dictionnaire :(


1 Je savais que vous pouviez parcourir les entrées du dictionnaire et trouver l'entrée appropriée de cette façon, mais je ne vois aucune raison pour laquelle vous voudriez le faire quand vous avez un indexeur parfaitement bon qui est O(1) au lieu de O (N).

41
Jon Skeet

Comme Dictionary<TKey, TValue> met en oeuvre IEnumerable<KeyValuePair<TKey, TValue>>, vous pouvez utiliser linq:

var pair = _dictionary.SingleOrDefault(p => p.Key == myKey);
18
Oliver Hanappi

Nous ne pouvons pas arriver à "IPHone" par ici:

var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
               {
                   { "IPHone", "TCP/IP honing tools" }
               };

Console.WriteLine(dict["iPhone"]); // "TCP/IP honing tools"
Console.WriteLine( ??? ); // "IPHone"

Il ne semble pas y avoir de solution O(1) avec l'API actuelle, mais le bouclage de toutes les entrées fonctionne:

var keyValue = dict.First(p => dict.Comparer.Equals(p.Key, "iPhone"));

Console.WriteLine(keyValue.Key); // "IPHone"
Console.WriteLine(keyValue.Value); // "TCP/IP honing tools"

Ou comme extension pour les paresseux:

[Pure]
public static KeyValuePair<TKey, TValue> GetEntry<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
{
    var comparer = dictionary.Comparer;
    return dictionary.FirstOrDefault(p => comparer.Equals(p.Key, key));
}
1
johv

Pour moi myDict.AsEnumerable le fait ...

0
Silvan Hofer