Quelle est la meilleure façon d’itérer sur un dictionnaire?

J’ai vu différentes manières d’itérer un dictionnaire en C #. Y a-t-il un moyen standard?

     foreach(KeyValuePair entry in myDictionary) { // do something with entry.Value or entry.Key } 

    Si vous essayez d’utiliser un dictionnaire générique en C # comme vous utiliseriez un tableau associatif dans une autre langue:

     foreach(var item in myDictionary) { foo(item.Key); bar(item.Value); } 

    Ou, si vous avez seulement besoin de parcourir la collection de clés, utilisez

     foreach(var item in myDictionary.Keys) { foo(item); } 

    Et enfin, si vous n’êtes intéressé que par les valeurs:

     foreach(var item in myDictionary.Values) { foo(item); } 

    (Notez que le mot-clé var est une fonctionnalité facultative C # 3.0 et supérieure, vous pouvez également utiliser le type exact de vos clés / valeurs ici)

    Dans certains cas, vous pouvez avoir besoin d’un compteur pouvant être fourni par l’implémentation en boucle. Pour cela, LINQ fournit ElementAt qui permet:

     for (int index = 0; index < dictionary.Count; index++) { var item = dictionary.ElementAt(index); var itemKey = item.Key; var itemValue = item.Value; } 

    Cela dépend si vous recherchez les clés ou les valeurs …

    Depuis le Dictionary(TKey, TValue) MSDN Dictionary(TKey, TValue) Description de la classe:

     // When you use foreach to enumerate dictionary elements, // the elements are resortingeved as KeyValuePair objects. Console.WriteLine(); foreach( KeyValuePair kvp in openWith ) { Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value); } // To get the values alone, use the Values property. Dictionary.ValueCollection valueColl = openWith.Values; // The elements of the ValueCollection are strongly typed // with the type that was specified for dictionary values. Console.WriteLine(); foreach( ssortingng s in valueColl ) { Console.WriteLine("Value = {0}", s); } // To get the keys alone, use the Keys property. Dictionary.KeyCollection keyColl = openWith.Keys; // The elements of the KeyCollection are strongly typed // with the type that was specified for dictionary keys. Console.WriteLine(); foreach( ssortingng s in keyColl ) { Console.WriteLine("Key = {0}", s); } 

    Généralement, demander «la meilleure façon» sans contexte spécifique revient à demander quelle est la meilleure couleur.

    D’une part, il y a beaucoup de couleurs et il n’y a pas de meilleure couleur. Cela dépend aussi du besoin et souvent du goût.

    D’un autre côté, il existe de nombreuses manières d’itérer un dictionnaire en C # et il n’y a pas de meilleur moyen. Cela dépend aussi du besoin et souvent du goût.

    Manière la plus simple

     foreach (var kvp in items) { // key is kvp.Key doStuff(kvp.Value) } 

    Si vous n’avez besoin que de la valeur (permet de l’appeler item , plus lisible que kvp.Value ).

     foreach (var item in items.Values) { doStuff(item) } 

    Si vous avez besoin d’un ordre de sorting spécifique

    En général, les débutants sont surpris par l’ordre d’énumération d’un dictionnaire.

    LINQ fournit une syntaxe concise qui permet de spécifier l’ordre (et beaucoup d’autres choses), par exemple:

     foreach (var kvp in items.OrderBy(kvp => kvp.Key)) { // key is kvp.Key doStuff(kvp.Value) } 

    Encore une fois, vous pourriez seulement avoir besoin de la valeur. LINQ fournit également une solution concise pour:

    • itère directement sur la valeur (permet de l’appeler item , plus lisible que kvp.Value )
    • mais sortingé par les clés

    C’est ici:

     foreach (var item in items.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value)) { doStuff(item) } 

    Il y a beaucoup d’autres cas d’utilisation réels que vous pouvez faire avec ces exemples. Si vous n’avez pas besoin d’un ordre spécifique, respectez simplement la méthode la plus simple (voir ci-dessus)!

    Je dirais que foreach est la méthode standard, mais cela dépend évidemment de ce que vous recherchez

     foreach(var kvp in my_dictionary) { ... } 

    Est-ce ce que vous cherchez?

    Vous pouvez également essayer cela sur les grands dictionnaires pour le traitement multithread.

     dictionary .AsParallel() .ForAll(pair => { // Process pair.Key and pair.Value here }); 

    Il y a plein d’options. Mon préféré est par KeyValuePair

     Dictionary myDictionary = new Dictionary(); // Populate your dictionary here foreach (KeyValuePair kvp in myDictionary) { // Do some interesting things } 

    Vous pouvez également utiliser les collections de clés et de valeurs

    J’apprécie cette question a déjà eu beaucoup de réponses, mais je voulais jeter un peu de recherche.

    Itérer sur un dictionnaire peut être assez lent comparé à une itération sur un tableau. Dans mes tests, une itération sur un tableau a pris 0.015003 secondes alors qu’une itération sur un dictionnaire (avec le même nombre d’éléments) a pris 0.0365073 secondes, soit 2.4 fois plus! Bien que j’ai vu beaucoup plus de différences. A titre de comparaison, une liste se situait quelque part entre 0,00215043 seconde.

    Cependant, c’est comme comparer des pommes et des oranges. Mon point est que l’itération sur les dictionnaires est lente.

    Les dictionnaires sont optimisés pour les recherches, c’est pourquoi j’ai créé deux méthodes. On fait simplement un foreach, l’autre itère les clés puis regarde.

     public static ssortingng Normal(Dictionary dictionary) { ssortingng value; int count = 0; foreach (var kvp in dictionary) { value = kvp.Value; count++; } return "Normal"; } 

    Celui-ci charge les clés et les itère au lieu de cela (j’ai aussi essayé de tirer les clés dans une chaîne [] mais la différence était négligeable.

     public static ssortingng Keys(Dictionary dictionary) { ssortingng value; int count = 0; foreach (var key in dictionary.Keys) { value = dictionary[key]; count++; } return "Keys"; } 

    Avec cet exemple, le test foreach normal a pris 0.0310062 et la version des clés a pris 0.2205441. Charger toutes les clés et itérer sur toutes les recherches est nettement plus lent!

    Pour un test final, j’ai effectué mon itération dix fois pour voir s’il y avait des avantages à utiliser les clés ici (à ce stade, j’étais simplement curieux):

    Voici la méthode RunTest si cela vous aide à visualiser ce qui se passe.

     private static ssortingng RunTest(T dictionary, Func function) { DateTime start = DateTime.Now; ssortingng name = null; for (int i = 0; i < 10; i++) { name = function(dictionary); } DateTime end = DateTime.Now; var duration = end.Subtract(start); return string.Format("{0} took {1} seconds", name, duration.TotalSeconds); } 

    Ici, l'exécution normale de foreach a pris 0,2820564 secondes (environ dix fois plus longtemps qu'une seule itération a eu lieu, comme on pouvait s'y attendre). L'itération sur les clés a pris 2,2249449 secondes.

    Edité pour append: En lisant certaines des autres réponses, je me suis demandé ce qui se passerait si j'utilisais Dictionary au lieu de Dictionary. Dans cet exemple, le tableau a pris 0.0120024 secondes, la liste 0.0185037 secondes et le dictionnaire 0.0465093 secondes. Il est raisonnable de s'attendre à ce que le type de données fasse une différence sur le ralentissement du dictionnaire.

    Quelles sont mes conclusions ?

    • Évitez de parcourir un dictionnaire si vous le pouvez, ils sont considérablement plus lents que les itérations sur un tableau contenant les mêmes données.
    • Si vous choisissez de parcourir un dictionnaire, n'essayez pas d'être trop intelligent, même si plus lentement, vous pourriez faire beaucoup plus mal que d'utiliser la méthode foreach standard.

    Vous avez suggéré ci-dessous d’itérer

     Dictionary myDictionary = new Dictionary(); //Populate your dictionary here foreach (KeyValuePair kvp in myDictionary) { //Do some interesting things; } 

    FYI, foreach ne fonctionne pas si la valeur est de type object.

    Avec .NET Framework 4.7 on peut utiliser la décomposition

     var fruits = new Dictionary(); ... foreach (var (fruit, number) in fruits) { Console.WriteLine(fruit + ": " + number); } 

    Pour que ce code fonctionne sur les versions C # inférieures, ajoutez le System.ValueTuple NuGet package et écrivez quelque part

     public static class MyExtensions { public static void Deconstruct(this KeyValuePair tuple, out T1 key, out T2 value) { key = tuple.Key; value = tuple.Value; } } 

    Forme la plus simple pour itérer un dictionnaire:

     foreach(var item in myDictionary) { Console.WriteLine(item.Key); Console.WriteLine(item.Value); } 

    Parfois, si vous n’avez besoin que des valeurs à énumérer, utilisez la collection de valeurs du dictionnaire:

     foreach(var value in dictionary.Values) { // do something with entry.Value only } 

    Signalé par ce post qui indique que c’est la méthode la plus rapide: http://alexpinsker.blogspot.hk/2010/02/c-fastest-way-to-iterate-over.html

    J’ai trouvé cette méthode dans la documentation de la classe DictionaryBase sur MSDN:

     foreach (DictionaryEntry de in myDictionary) { //Do some stuff with de.Value or de.Key } 

    C’était le seul que je pouvais faire fonctionner correctement dans une classe héritée de DictionaryBase.

    Je vais profiter de .NET 4.0+ et fournir une réponse actualisée à celle acceptée à l’origine:

     foreach(var entry in MyDic) { // do something with entry.Value or entry.Key } 

    Selon la documentation officielle sur MSDN, la méthode standard pour parcourir un dictionnaire est la suivante:

     foreach (DictionaryEntry entry in myDictionary) { //Read entry.Key and entry.Value here } 

    En utilisant C # 7 , ajoutez cette méthode d’extension à tout projet de votre solution:

     public static class IDictionaryExtensions { public static IEnumerable<(TKey, TValue)> Tuples( this IDictionary dict) { foreach (KeyValuePair kvp in dict) yield return (kvp.Key, kvp.Value); } } 

    Et utilisez cette syntaxe simple

     foreach (var(id, value) in dict.Tuples()) { // your code using 'id' and 'value' } 

    Ou celui-ci, si vous préférez

     foreach ((ssortingng id, object value) in dict.Tuples()) { // your code using 'id' and 'value' } 

    Au lieu du traditionnel

     foreach (KeyValuePair kvp in dict) { ssortingng id = kvp.Key; object value = kvp.Value; // your code using 'id' and 'value' } 

    La méthode d’extension transforme le KeyValuePair de votre IDictionary en un tuple fortement typé, vous permettant d’utiliser cette nouvelle syntaxe confortable.

    Il convertit -just les entrées de dictionnaire requirejses en tuples , de sorte qu’il ne convertit PAS tout le dictionnaire en tuples , il n’y a donc aucun problème de performance lié à cela.

    Il existe un coût mineur pour appeler la méthode d ‘extension pour créer un tuple par rapport à l’ utilisation directe de KeyValuePair , ce qui NE devrait PAS poser problème si vous atsortingbuez les propriétés Key et Value aux nouvelles variables de boucle.

    En pratique, cette nouvelle syntaxe convient très bien à la plupart des cas, sauf pour les scénarios de très haut niveau de très faible niveau de performance, où vous avez toujours la possibilité de ne pas l’utiliser sur cet emplacement spécifique.

    Jetez un coup d’ œil à ceci: Blog MSDN – Nouvelles fonctionnalités de C # 7

    Si, par exemple, vous voulez parcourir la collection de valeurs par défaut, je pense que vous pouvez implémenter IEnumerable <>, où T est le type de l’objet valeurs dans le dictionnaire, et “this” est un dictionnaire.

     public new IEnumerator GetEnumerator() { return this.Values.GetEnumerator(); } 

    A partir de C # 7, vous pouvez déconstruire des objects en variables. Je crois que c’est la meilleure façon de parcourir un dictionnaire.

    Exemple:

    Créez une méthode d’extension sur KeyValuePair qui la déconstruit:

     public static void Deconstruct(this KeyValuePair pair, out TKey, out TVal val) { key = pair.Key; val = pair.Value; } 

    Itérer sur n’importe quel Dictionary de la manière suivante

     // Dictionary can be of any types, just using 'int' and 'ssortingng' as examples. Dictionary dict = new Dictionary(); // Deconstructor gets called here. foreach (var (key, value) in dict) { Console.WriteLine($"{key} : {value}"); } 
     var dictionary = new Dictionary { { "Key", 12 } }; var aggregateObjectCollection = dictionary.Select( entry => new AggregateObject(entry.Key, entry.Value)); 

    Je voulais juste append mon 2 cent, comme la plupart des réponses concernent la boucle foreach. S’il vous plaît, jetez un oeil au code suivant:

     Dictionary myProductPrices = new Dictionary(); //Add some ensortinges to the dictionary myProductPrices.ToList().ForEach(kvP => { kvP.Value *= 1.15; Console.Writeline(Ssortingng.Format("Product '{0}' has a new price: {1} $", kvp.Key, kvP.Value)); }); 

    Si cela ajoute un appel supplémentaire de ‘.ToList ()’, il pourrait y avoir une légère amélioration des performances (comme indiqué ici foreach vs someList.Foreach () {} ), en particulier lorsque vous travaillez avec de grands dictionnaires et que l’exécution en parallèle est non option / n’aura aucun effet.

    Notez également que vous ne pourrez pas affecter de valeurs à la propriété ‘Value’ dans une boucle foreach. D’autre part, vous pourrez également manipuler la «clé», ce qui pourrait vous causer des problèmes lors de l’exécution.

    Lorsque vous souhaitez simplement “lire” des clés et des valeurs, vous pouvez également utiliser IEnumerable.Select ().

     var newProductPrices = myProductPrices.Select(kvp => new { Name = kvp.Key, Price = kvp.Value * 1.15 } ); 

    J’ai écrit une extension pour parcourir un dictionnaire.

     public static class DictionaryExtension { public static void ForEach(this Dictionary dictionary, Action action) { foreach(KeyValuePair keyValue in dictionary) { action(keyValue.Key, keyValue.Value); } } } 

    Ensuite, vous pouvez appeler

     myDictionary.ForEach((x,y) => Console.WriteLine(x + " - " + y)); 

    Dictionary C’est une classe de collection générique dans c # et elle stocke les données dans le format de la valeur de la clé. traité comme KeyValuePair structure représentant une clé et sa valeur. et donc nous devrions prendre le type d’élément KeyValuePair lors de l’itération de l’élément. Ci-dessous l’exemple.

     Dictionary dict = new Dictionary(); dict.Add(1,"One"); dict.Add(2,"Two"); dict.Add(3,"Three"); foreach (KeyValuePair item in dict) { Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value); } 

    en plus des plus hauts postes de classement où il y a une discussion entre l’utilisation

     foreach(KeyValuePair entry in myDictionary) { // do something with entry.Value or entry.Key } 

    ou

     foreach(var entry in myDictionary) { // do something with entry.Value or entry.Key } 

    le plus complet est le suivant parce que vous pouvez voir le type de dictionnaire à partir de l’initialisation, kvp est KeyValuePair

     var myDictionary = new Dictionary(x);//fill dictionary with x foreach(var kvp in myDictionary)//iterate over dictionary { // do something with kvp.Value or kvp.Key } 

    Les dictionnaires sont des listes spéciales, alors que toutes les valeurs de la liste ont une clé qui est également une variable. Un bon exemple de dictionnaire est un annuaire téléphonique.

      Dictionary phonebook = new Dictionary(); phonebook.Add("Alex", 4154346543); phonebook["Jessica"] = 4159484588; 

    Notez que lors de la définition d’un dictionnaire, nous devons fournir une définition générique avec deux types: le type de la clé et le type de la valeur. Dans ce cas, la clé est une chaîne alors que la valeur est un entier.

    Il existe également deux manières d’append une valeur unique au dictionnaire, à l’aide de l’opérateur entre crochets ou de la méthode Add.

    Pour vérifier si un dictionnaire contient une certaine clé, nous pouvons utiliser la méthode ContainsKey:

     Dictionary phonebook = new Dictionary(); phonebook.Add("Alex", 415434543); phonebook["Jessica"] = 415984588; if (phonebook.ContainsKey("Alex")) { Console.WriteLine("Alex's number is " + phonebook["Alex"]); } 

    Pour supprimer un élément d’un dictionnaire, nous pouvons utiliser la méthode Remove. Supprimer un élément d’un dictionnaire par sa clé est rapide et très efficace. Lors de la suppression d’un élément d’une liste à l’aide de sa valeur, le processus est lent et inefficace, contrairement à la fonction de suppression du dictionnaire.

     Dictionary phonebook = new Dictionary(); phonebook.Add("Alex", 415434543); phonebook["Jessica"] = 415984588; phonebook.Remove("Jessica"); Console.WriteLine(phonebook.Count);