c# dictionary example - Quel est le meilleur moyen de parcourir un dictionnaire?




13 Answers

foreach(KeyValuePair<string, string> entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}
foreach get

J'ai vu différentes façons de parcourir un dictionnaire en C #. Y a-t-il un moyen standard?




Dans certains cas, vous aurez peut-être besoin d'un compteur fourni par l'implémentation à boucle forée. 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;
}



De manière générale, 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 du besoin et souvent du goût.

D'autre part, il existe de nombreuses façons de parcourir un dictionnaire en C # et il n'y a pas de meilleure façon. Cela dépend 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 tri spécifique

En règle générale, 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 bien 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 avoir besoin uniquement de la valeur LINQ fournit également une solution concise pour:

  • itérer directement sur la valeur (permet de l'appeler item , plus lisible que kvp.Value )
  • mais trié par les clés

C'est ici:

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

Il existe de nombreux autres cas d'utilisation réels que vous pouvez utiliser à partir de ces exemples. Si vous n'avez pas besoin d'une commande spécifique, tenez-vous-en au "moyen le plus simple" (voir ci-dessus)!




Vous pouvez également essayer ceci sur de gros dictionnaires pour un traitement multithread.

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



J'apprécie que cette question ait déjà suscité beaucoup de réponses, mais je voulais lancer un peu de recherche.

Itérer sur un dictionnaire peut être assez lent par rapport à itérer sur quelque chose comme un tableau. Dans mes tests, une itération sur un tableau prenait 0,015003 secondes, tandis qu'une itération sur un dictionnaire (avec le même nombre d'éléments) prenait 0,0365073 secondes, soit 2,4 fois plus longtemps! Bien que j'ai vu des différences beaucoup plus grandes. À des fins de comparaison, une liste se situait quelque part entre 0,00215043 seconde.

Cependant, c'est comme comparer des pommes et des oranges. Ce que je veux dire, c'est que parcourir des dictionnaires est lent.

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

public static string Normal(Dictionary<string, string> dictionary)
{
    string value;
    int count = 0;
    foreach (var kvp in dictionary)
    {
        value = kvp.Value;
        count++;
    }

    return "Normal";
}

Celui-ci charge les clés et les parcourt à la place (j'ai également essayé de tirer les clés dans une chaîne [] mais la différence était négligeable.

public static string Keys(Dictionary<string, string> dictionary)
{
    string value;
    int count = 0;
    foreach (var key in dictionary.Keys)
    {
        value = dictionary[key];
        count++;
    }

    return "Keys";
}

Dans cet exemple, le test foreach normal prenait 0.0310062 et la version de la clé prenait 0.2205441. Charger toutes les clés et parcourir toutes les recherches est clairement beaucoup plus lent!

Pour un dernier test, j'ai répété dix fois mon itération pour voir s'il y avait un quelconque avantage à 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 string RunTest<T>(T dictionary, Func<T, string> function)
{            
    DateTime start = DateTime.Now;
    string 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, le cycle normal de chaque opération a pris 0,2820564 secondes (environ dix fois plus longtemps qu’une seule itération - comme on pouvait s’y attendre). L'itération sur les clés a pris 2,2249449 secondes.

Edité à ajouter: La lecture de certaines des autres réponses m'a fait me demander ce qui se passerait si j'utilisais Dictionary au lieu de Dictionary. Dans cet exemple, le tableau prenait 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 influe sur la lenteur du dictionnaire.

Quelles sont mes conclusions ?

  • Évitez si possible de parcourir un dictionnaire, ils sont beaucoup plus lents que d’itérer sur un tableau contenant les mêmes données.
  • Si vous optez pour une itération par rapport à un dictionnaire, n'essayez pas d'être trop intelligent, même si vous ralentissez, vous pourriez faire bien pire que d'utiliser la méthode standard foreach.



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

Dictionary<string,object> myDictionary = new Dictionary<string,object>();
//Populate your dictionary here

foreach (KeyValuePair<string,object> kvp in myDictionary) {
    //Do some interesting things;
}

Pour votre information, foreach ne fonctionne pas si la valeur est de type objet.




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

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

Signalé par cet article qui déclare 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 obtenir de fonctionner correctement dans une classe héritée de DictionaryBase.




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
}



À partir de C # 7, vous pouvez décomposer des objets en variables. Je crois que c'est le meilleur moyen de parcourir un dictionnaire.

Exemple:

Créez une méthode d'extension sur KeyValuePair<TKey, TVal> qui la déconstruit:

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

Itérez sur n'importe quel Dictionary<TKey, TVal> de la manière suivante

// Dictionary can be of any types, just using 'int' and 'string' as examples.
Dictionary<int, string> dict = new Dictionary<int, string>();

// Deconstructor gets called here.
foreach (var (key, value) in dict)
{
   Console.WriteLine($"{key} : {value}");
}



Je voulais juste ajouter mon 2 cent, car la plupart des réponses concernent foreach-loop. S'il vous plaît, jetez un oeil sur le code suivant:

Dictionary<String, Double> myProductPrices = new Dictionary<String, Double>();

//Add some entries to the dictionary

myProductPrices.ToList().ForEach(kvP => 
{
    kvP.Value *= 1.15;
    Console.Writeline(String.Format("Product '{0}' has a new price: {1} $", kvp.Key, kvP.Value));
});

Bien que cela ajoute un appel supplémentaire de '.ToList ()', il pourrait y avoir une légère amélioration des performances option / n'aura aucun effet.

Veuillez également noter que vous ne pourrez pas attribuer de valeurs à la propriété 'Value' dans une boucle foreach. D'autre part, vous pourrez également manipuler la «clé», ce qui peut éventuellement vous causer des problèmes lors de l'exécution.

Lorsque vous voulez 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 } );



Dictionary <TKey, TValue> C’est une classe de collection générique en c # qui stocke les données dans le format de valeur de clé.Key doit être unique et ne peut pas être null alors que la valeur peut être dupliquée et nulle. traitée comme une structure KeyValuePair <TKey, TValue> représentant une clé et sa valeur. et par conséquent nous devrions prendre le type d'élément KeyValuePair <TKey, TValue> lors de l'itération de l'élément. Voici l'exemple.

Dictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(1,"One");
dict.Add(2,"Two");
dict.Add(3,"Three");

foreach (KeyValuePair<int, string> item in dict)
{
    Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
}



Les dictionnaires sont des listes spéciales, alors que chaque valeur de la liste a une clé qui est aussi une variable. Un bon exemple de dictionnaire est un annuaire téléphonique.

   Dictionary<string, long> phonebook = new Dictionary<string, long>();
    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 façons d'ajouter une seule valeur au dictionnaire, en utilisant l'opérateur de crochets ou en utilisant la méthode Add.

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

Dictionary<string, long> phonebook = new Dictionary<string, long>();
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. Lorsque vous supprimez un élément d'une liste en utilisant sa valeur, le processus est lent et inefficace, contrairement à la fonction de suppression du dictionnaire.

Dictionary<string, long> phonebook = new Dictionary<string, long>();
phonebook.Add("Alex", 415434543);
phonebook["Jessica"] = 415984588;

phonebook.Remove("Jessica");
Console.WriteLine(phonebook.Count);



Related