web-dev-qa-db-fra.com

Obtenir l'index d'une paire clé / valeur dans un dictionnaire C # en fonction de la valeur

Je voudrais savoir s'il existe une propriété ou une méthode qui obtient l'index d'une valeur spécifique.

J'ai trouvé que les dictionnaires ont la méthode Contains() qui retourne vrai si la valeur passée existe, donc cette méthode implémente presque ce dont j'ai besoin.

Je sais que je peux parcourir toutes les paires de valeurs et vérifier la condition, mais je demande parce qu'il y a peut-être une façon optimisée de le faire.

34
mjsr

Il n'y a pas un tel concept d'un "index" dans un dictionnaire - il est fondamentalement non ordonné. Bien sûr, lorsque vous itérez dessus, vous obtiendrez les articles dans l'ordre certains, mais cet ordre n'est pas garanti et peut changer au fil du temps (en particulier si vous ajoutez ou supprimez des entrées).

Évidemment, vous pouvez obtenir la clé d'un KeyValuePair simplement en utilisant la propriété Key, ce qui vous permettra d'utiliser l'indexeur du dictionnaire:

var pair = ...;
var value = dictionary[pair.Key];
Assert.AreEqual(value, pair.Value);

Vous n'avez pas vraiment dit ce que vous essayez de faire. Si vous essayez de trouver une clé qui correspond à une valeur particulière, vous pouvez utiliser:

var key = dictionary.Where(pair => pair.Value == desiredValue)
                    .Select(pair => pair.Key)
                    .FirstOrDefault();

key sera nul si l'entrée n'existe pas.

Cela suppose que le type de clé est un type de référence ... s'il s'agit d'un type de valeur, vous devrez faire les choses légèrement différemment.

Bien sûr, si vous voulez vraiment rechercher des valeurs par clé, vous devriez envisager d'utiliser un autre dictionnaire qui mappe l'inverse en plus de votre dictionnaire existant.

30
Jon Skeet

Disons que vous avez un dictionnaire appelé fooDictionary

fooDictionary.Values.ToList().IndexOf(someValue);

Values.ToList () convertit les valeurs de votre dictionnaire en une liste d'objets someValue.

IndexOf (someValue) recherche dans votre nouvelle liste à la recherche de l'objet someValue en question et renvoie l'index qui correspondrait à l'index de la paire clé/valeur dans le dictionnaire.

Cette méthode ne se soucie pas des clés de dictionnaire, elle renvoie simplement l'index de la valeur que vous recherchez.

Toutefois, cela ne tient pas compte du fait qu'il peut y avoir plusieurs objets "someValue" correspondants.

24
EricM

Pensez à utiliser System.Collections.Specialized.OrderedDictionary , bien qu'il ne soit pas générique, ou implémentez le vôtre ( exemple ).

OrderedDictionary ne prend pas en charge IndexOf, mais il est facile à implémenter:

public static class OrderedDictionaryExtensions
{
    public static int IndexOf(this OrderedDictionary dictionary, object value)
    {
        for(int i = 0; i < dictionary.Count; ++i)
        {
            if(dictionary[i] == value) return i;
        }
        return -1;
    }
}
9
max

Vous pouvez utiliser LINQ pour vous aider.

Dictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(1, "hi");
dict.Add(2, "NotHi");
dict.Add(3, "Bah");

var item = (from d in dict
            where d.Value == "hi"
            select d.Key).FirstOrDefault();

Console.WriteLine(item); //Prints 1
2
George Stocker
 Vous pouvez trouver l'index par clé/valeurs dans le dictionnaire 
Dictionary<string, string> myDictionary = new Dictionary<string, string>();
myDictionary.Add("a", "x");
myDictionary.Add("b", "y");
int i = Array.IndexOf(myDictionary.Keys.ToArray(), "a");
int j = Array.IndexOf(myDictionary.Values.ToArray(), "y");
2
malik

Si vous recherchez une valeur, vous devrez parcourir toutes les données. Mais pour minimiser le code impliqué, vous pouvez utiliser LINQ.

Exemple:

Dictionnaire donné défini comme suit:

Dictionary<Int32, String> dict;

Vous pouvez utiliser le code suivant:

// Search for all keys with given value
Int32[] keys = dict.Where(kvp => kvp.Value.Equals("SomeValue")).Select(kvp => kvp.Key).ToArray();

// Search for first key with given value
Int32 key = dict.First(kvp => kvp.Value.Equals("SomeValue")).Key;
1
decyclone

non, il n'y a rien de similaire IndexOf for Dictionary bien que vous puissiez utiliser la méthode ContainsKey pour savoir si une clé appartient au dictionnaire ou non

0
TalentTuner

Dans votre commentaire à maxréponse , vous dites que ce que vous vouliez vraiment obtenir, c'est la touche dans, et pas l'index de, KeyValuePair qui contient une certaine valeur. Vous pouvez modifier votre question pour la rendre plus claire.

Il convient de souligner ( EricM a abordé ce sujet dans son réponse ) qu'une valeur peut apparaître plus d'une fois dans le dictionnaire, dans ce cas, il faudrait penser à quelle clé il aimerait obtenir: par exemple le premier qui arrive, le dernier, tous?

Si vous êtes sûr que chaque clé a une valeur unique, vous pouvez avoir un autre dictionnaire, avec les valeurs de la première agissant comme clés et les clés précédentes agissant comme valeurs. Sinon, cette deuxième idée de dictionnaire ( suggérée par Jon Skeet ) ne fonctionnera pas, car vous devrez à nouveau penser laquelle de toutes les clés possibles à utiliser comme valeur dans le nouveau dictionnaire.

Si vous étiez posant des questions sur l'index, cependant, la réponse d'EricM serait OK. Ensuite, vous pouvez obtenir le KeyValuePair en question en utilisant:

yourDictionary.ElementAt(theIndexYouFound);

à condition que vous n'ajoutiez/supprimiez pas de choses dans yourDictionary.

PS: Je sais que ça fait presque 7 ans maintenant, mais qu'est-ce que ça fait. J'ai pensé qu'il était préférable de formuler ma réponse comme s'adressant à l'OP, mais bien sûr, maintenant on peut dire que c'est une réponse pour à peu près n'importe qui d'autre mais l'OP. Pleinement conscient de cela, merci.

0
zerzevul