Il est facile d'obtenir la valeur d'une clé à partir d'un dictionnaire générique .NET:
Dictionary<int, string> greek = new Dictionary<int, string>();
greek.Add(1, "Alpha");
greek.Add(2, "Beta");
string secondGreek = greek[2]; // Beta
Mais essayer d'obtenir les clés avec une valeur n'est pas aussi simple car il pourrait y avoir plusieurs clés:
int[] betaKeys = greek.WhatDoIPutHere("Beta"); // expecting single 2
int[]
lorsque vous attendez une valeur unique?Réponses:
D'accord, voici la version bidirectionnelle multiple:
la source
Comme tout le monde l'a dit, il n'y a pas de mappage dans un dictionnaire d'une valeur à une clé.
Je viens de remarquer que vous vouliez mapper de valeur à plusieurs clés - je laisse cette solution ici pour la version à valeur unique, mais j'ajouterai ensuite une autre réponse pour une carte bidirectionnelle à entrées multiples.
L'approche normale à adopter ici est d'avoir deux dictionnaires - un mappage dans un sens et l'autre. Encapsulez-les dans une classe séparée et déterminez ce que vous voulez faire lorsque vous avez une clé ou une valeur en double (par exemple, lever une exception, écraser l'entrée existante ou ignorer la nouvelle entrée). Personnellement, j'irais probablement pour lancer une exception - cela rend le comportement de réussite plus facile à définir. Quelque chose comme ça:
la source
Add
appels au dictionnaire échouera - mais si c'est le second, nous avons alors mis le système dans un état confus. Ma façon, vous avez toujours une collection cohérente après l'exception.Les dictionnaires ne sont pas vraiment censés fonctionner comme ça, car si l'unicité des clés est garantie, l'unicité des valeurs ne l'est pas. Donc par exemple si vous aviez
À quoi vous attendriez-vous
greek.WhatDoIPutHere("Alpha")
?Par conséquent, vous ne pouvez pas vous attendre à ce que quelque chose comme ça soit intégré dans le framework. Vous auriez besoin de votre propre méthode pour vos propres utilisations uniques --- voulez-vous retourner un tableau (ou
IEnumerable<T>
)? Voulez-vous lever une exception s'il existe plusieurs clés avec la valeur donnée? Et s'il n'y en a pas?Personnellement, je choisirais un énumérable, comme ceci:
la source
Peut-être que la façon la plus simple de le faire, sans Linq, peut être de boucler sur les paires:
Si vous aviez Linq, cela aurait pu faire facilement de cette façon:
la source
var
est une fonctionnalité de langage, pas une fonctionnalité de cadre. Vous pouvez utiliser la fusion nulle à partir de C # -6.0 et toujours cibler CF-2.0 si vous le souhaitez vraiment.Un dictionnaire ne conserve pas un hachage des valeurs, seulement les clés, donc toute recherche dessus en utilisant une valeur va prendre au moins un temps linéaire. Votre meilleur pari est simplement de parcourir les éléments du dictionnaire et de garder une trace des clés correspondantes ou de passer à une structure de données différente, peut-être de conserver deux mappages de dictionnaire clé-> valeur et valeur-> List_of_keys. Si vous faites ce dernier, vous échangerez du stockage contre de la vitesse de recherche. Il ne faudrait pas grand-chose pour transformer l'exemple @Cybis en une telle structure de données.
la source
Comme je voulais un dictionnaire bi-directionnel à part entière (et pas seulement une carte), j'ai ajouté les fonctions manquantes pour en faire une classe compatible IDictionary. Ceci est basé sur la version avec des paires clé-valeur uniques. Voici le fichier si vous le souhaitez (la plupart du travail était le XMLDoc):
la source
révisé: d'accord pour avoir une sorte de recherche, vous auriez besoin d'autre chose que d'un dictionnaire, car si vous y pensez, les dictionnaires sont des clés à sens unique. autrement dit, les valeurs peuvent ne pas être uniques
Cela dit, il semble que vous utilisez c # 3.0, vous n'aurez donc peut-être pas à recourir à la boucle et vous pourriez utiliser quelque chose comme:
la source
La classe Dictionary n'est pas optimisée pour ce cas, mais si vous vouliez vraiment le faire (en C # 2.0), vous pouvez faire:
Je préfère la solution LINQ pour l'élégance, mais c'est la voie 2.0.
la source
Ne pouvez-vous pas créer une sous-classe de Dictionary qui a cette fonctionnalité?
EDIT: Désolé, je n'ai pas reçu le code du premier coup.
la source
La solution de dictionnaire bidirectionnel «simple» proposée ici est complexe et peut être difficile à comprendre, à maintenir ou à étendre. Aussi la question originale demandait "la clé pour une valeur", mais clairement il pourrait y avoir plusieurs clés (j'ai depuis édité la question). L'approche dans son ensemble est plutôt suspecte.
Modifications du logiciel. L'écriture de code facile à maintenir doit avoir la priorité sur d'autres solutions de contournement complexes «intelligentes». La façon de récupérer des clés à partir des valeurs d'un dictionnaire est de faire une boucle. Un dictionnaire n'est pas conçu pour être bidirectionnel.
la source
int
valeurs parstring
clé, le dictionnaire peut être défini comme suit:Dictionary<string, List<int>>
.Dictionary
n'offre pas de capacité bidirectionnelle. Donc, si tout ce que vous avez est un standardDictionary
et que vous souhaitez trouver la ou les clés associées à une valeur spécifique, vous devez en effet itérer! Cependant, pour les dictionnaires «volumineux», l'itération peut entraîner de mauvaises performances. Notez que la réponse que j'ai moi-même proposée est basée sur l'itération (via LINQ). Si votre initialeDictionary
n'est pas sujette à d'autres modifications, vous pouvez créer une inverseDictionary
une fois pour accélérer les recherches inversées.Utilisez LINQ pour effectuer une
Dictionary<K, V>
recherche inversée . Mais gardez à l'esprit que les valeurs de vosDictionary<K, V>
valeurs peuvent ne pas être distinctes.Manifestation:
Production attendue:
la source
la source
Comme une torsion de la réponse acceptée ( https://stackoverflow.com/a/255638/986160 ) en supposant que les clés seront associées à des valeurs de signle dans le dictionnaire. Similaire à ( https://stackoverflow.com/a/255630/986160 ) mais un peu plus élégant. La nouveauté réside dans le fait que la classe consommatrice peut être utilisée comme alternative d'énumération (mais aussi pour les chaînes) et que le dictionnaire implémente IEnumerable.
Et en tant que classe consommatrice, vous pourriez avoir
la source
Puis la solution du profane
Une fonction similaire à celle ci-dessous pourrait être écrite pour créer un tel dictionnaire:
la source