Question

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

Était-ce utile?

La solution

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

Autres conseils

Si vous essayez d'utiliser un dictionnaire générique en C #, utilisez un tableau associatif dans une autre langue:

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

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

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

Et enfin, si vous ne vous intéressez qu'aux valeurs:

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

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

Dans certains cas, vous aurez peut-être besoin d'un compteur fourni par la mise en œuvre de boucle for. 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 êtes après les clés ou les valeurs ...

À partir du fichier MSDN Dictionary(TKey, TValue) Description de la classe:

// When you use foreach to enumerate dictionary elements,
// the elements are retrieved as KeyValuePair objects.
Console.WriteLine();
foreach( KeyValuePair<string, string> kvp in openWith )
{
    Console.WriteLine("Key = {0}, Value = {1}", 
        kvp.Key, kvp.Value);
}

// To get the values alone, use the Values property.
Dictionary<string, string>.ValueCollection valueColl =
    openWith.Values;

// The elements of the ValueCollection are strongly typed
// with the type that was specified for dictionary values.
Console.WriteLine();
foreach( string s in valueColl )
{
    Console.WriteLine("Value = {0}", s);
}

// To get the keys alone, use the Keys property.
Dictionary<string, string>.KeyCollection keyColl =
    openWith.Keys;

// The elements of the KeyCollection are strongly typed
// with the type that was specified for dictionary keys.
Console.WriteLine();
foreach( string s in keyColl )
{
    Console.WriteLine("Key = {0}", s);
}

En général, demander & "La meilleure façon &" sans contexte spécifique est comme 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 des besoins 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 des besoins et souvent du goût.

La 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 encore), par exemple:

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

Encore une fois, vous n’avez peut-être besoin que de la valeur. LINQ fournit également une solution concise pour:

  • itérer directement sur la valeur (permet de l'appeler <=>, plus lisible que <=>)
  • mais trié par les clés

La voici:

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

À partir de ces exemples, vous pouvez utiliser de nombreux autres cas d'utilisation réels. Si vous n'avez pas besoin d'une commande spécifique, restez dans le & "Moyen le plus simple ." (voir ci-dessus)!

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

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

Est-ce ce que vous cherchez?

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

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

Il existe de nombreuses options. Mon préféré est par KeyValuePair

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

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

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

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 comparé à une itération 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. À titre de comparaison, la liste se situait quelque part entre 0,00215043 secondes.

Cependant, cela revient à comparer des pommes et des oranges. Mon argument est que parcourir les dictionnaires est lent.

Les dictionnaires étant optimisés pour les recherches, j'ai donc 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 itère à 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";
}

Avec 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 était avantageux d'utiliser les clés ici (à ce moment-là, 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, la course normale pour chaque opération a pris 0,2820564 secondes (environ dix fois plus longtemps qu’une seule itération - comme vous l’attendiez). L’itération sur les clés a pris 2,2249449 secondes.

Modifié pour ajouter: La lecture de certaines des autres réponses m'a fait me demander ce qui se passerait si j'utilisais Dictionnaire au lieu de Dictionnaire. 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 choisissez de parcourir un dictionnaire, n'essayez pas d'être trop intelligent, mais vous pourriez faire beaucoup moins vite que d'utiliser la méthode standard foreach.

C # 7.0 a présenté Les déconstructeurs et si vous utilisez l'application .NET Core 2.0 + , la structure KeyValuePair<> inclut déjà un Deconstruct() pour vous. Donc vous pouvez faire:

var dic = new Dictionary<int, string>() { { 1, "One" }, { 2, "Two" }, { 3, "Three" } };
foreach (var (key, value) in dic) {
    Console.WriteLine($"Item [{key}] = {value}");
}
//Or
foreach (var (_, value) in dic) {
    Console.WriteLine($"Item [NO_ID] = {value}");
}
//Or
foreach ((int key, string value) in dic) {
    Console.WriteLine($"Item [{key}] = {value}");
}

 entrez la description de l'image ici

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 info, foreach ne fonctionne pas si la valeur est de type objet.

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

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

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

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

La forme la plus simple pour itérer un dictionnaire:

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

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<TKey, TValue>(
        this IDictionary<TKey, TValue> dict)
    {
        foreach (KeyValuePair<TKey, TValue> 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 ((string id, object value) in dict.Tuples())
{
    // your code using 'id' and 'value'
}


À la place du traditionnel

foreach (KeyValuePair<string, object> kvp in dict)
{
    string id = kvp.Key;
    object value = kvp.Value;

    // your code using 'id' and 'value'
}


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

Il convertit -just- les entrées de dictionnaire requises en tuples. Par conséquent, il ne convertit PAS l'intégralité du dictionnaire en Key. Il n'y a donc pas de problème de performances.

Il existe un coût mineur d'appeler la méthode d'extension pour créer un Value en comparaison avec l'utilisation directe de <=>, ce qui ne devrait PAS être un problème si vous affectez les propriétés de <=> <=> et <=> aux nouvelles variables de boucle quand même.

En pratique, cette nouvelle syntaxe convient très bien dans la plupart des cas, à l'exception des scénarios de performances ultra-hautes performances de bas niveau, où vous avez toujours la possibilité de ne pas l'utiliser tout simplement à cet endroit spécifique.

Découvrez ceci: Blog MSDN - Nouvelles fonctionnalités de C # 7

Parfois, si vous souhaitez uniquement énumérer les valeurs, utilisez la collection de valeurs du dictionnaire:

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

Rapporté 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’est le seul que j’ai réussi à faire fonctionner correctement dans une classe héritée de DictionaryBase.

Je vais tirer parti de .NET 4.0+ et fournir une réponse mise à jour à celle initialement acceptée:

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

La méthode standard pour parcourir un dictionnaire, selon la documentation officielle sur MSDN, 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 pense 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érer sur tout 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}");
}

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 de valeurs dans le dictionnaire et "ceci &" est un dictionnaire.

public new IEnumerator<T> GetEnumerator()
{
   return this.Values.GetEnumerator();
}
var dictionary = new Dictionary<string, int>
{
    { "Key", 12 }
};

var aggregateObjectCollection = dictionary.Select(
    entry => new AggregateObject(entry.Key, entry.Value));

Je voulais juste ajouter mon 2 cent, car la plupart des réponses concernent foreach-loop. Veuillez regarder 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 (comme indiqué ici foreach vs someList.Foreach () {} ), en particulier lorsque vous travaillez avec de grands dictionnaires et que vous travaillez en parallèle, ce n’est pas une 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 peut éventuellement vous causer des ennuis au moment de l'exécution.

Quand vous voulez juste & "lire &"; Clés et 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 boucler un dictionnaire.

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

Ensuite, vous pouvez appeler

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

Je sais que la question est très ancienne, mais j’ai créé des méthodes d’extension qui pourraient être utiles:

    public static void ForEach<T, U>(this Dictionary<T, U> d, Action<KeyValuePair<T, U>> a)
    {
        foreach (KeyValuePair<T, U> p in d) { a(p); }
    }

    public static void ForEach<T, U>(this Dictionary<T, U>.KeyCollection k, Action<T> a)
    {
        foreach (T t in k) { a(t); }
    }

    public static void ForEach<T, U>(this Dictionary<T, U>.ValueCollection v, Action<U> a)
    {
        foreach (U u in v) { a(u); }
    }

De cette façon, je peux écrire du code comme ceci:

myDictionary.ForEach(pair => Console.Write($"key: {pair.Key}, value: {pair.Value}"));
myDictionary.Keys.ForEach(key => Console.Write(key););
myDictionary.Values.ForEach(value => Console.Write(value););

Dictionnaire < TKey, & # 8194; TValue & Gt; Il s'agit d'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 value peut be duplicate and null.As chaque élément du dictionnaire est traité comme KeyValuePair < TKey, & # 8194; TValue & Gt; structure représentant une clé et sa valeur. et par conséquent nous devrions prendre le type d'élément KeyValuePair < TKey, & # 8194; TValue & Gt; 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);
}

en plus des postes de plus haut rang où il y a une discussion entre utiliser

foreach(KeyValuePair<string, string> 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 car vous pouvez voir le type de dictionnaire dès l’initialisation, kvp est KeyValuePair

var myDictionary = new Dictionary<string, string>(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 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 un générique    définition 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'ajouter une seule valeur au dictionnaire, en utilisant l'opérateur de parenthèses 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);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top