Frage Was ist der beste Weg, um über ein Wörterbuch zu iterieren?


Ich habe ein paar verschiedene Möglichkeiten gesehen, über ein Wörterbuch in C # zu iterieren. Gibt es einen Standardweg?


1944
2017-09-26 18:20


Ursprung


Antworten:


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

2892
2017-09-26 18:22



Wenn Sie versuchen, ein generisches Dictionary in C # zu verwenden, würden Sie ein assoziatives Array in einer anderen Sprache verwenden:

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

Oder, wenn Sie nur über die Sammlung von Schlüsseln iterieren müssen, verwenden Sie

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

Und wenn Sie nur an den Werten interessiert sind:

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

(Beachten Sie, dass die var Schlüsselwort ist eine optionale C # 3.0 und höher Funktion, Sie könnten auch den genauen Typ Ihrer Schlüssel / Werte hier verwenden)


643
2017-09-26 18:22



In einigen Fällen benötigen Sie möglicherweise einen Zähler, der von der Implementierung der for-Schleife bereitgestellt werden kann. Dafür bietet LINQ ElementAt das ermöglicht Folgendes:

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

107
2018-03-10 20:44



Hängt davon ab, ob Sie nach den Schlüsseln oder den Werten suchen ...

Von der MSDN Dictionary(TKey, TValue) Klassenbeschreibung:

// 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);
}

74
2017-09-26 18:27



Im Allgemeinen ist die Frage nach dem "besten Weg" ohne einen spezifischen Kontext wie die Frage nach der besten Farbe.

Auf der einen Seite gibt es viele Farben und es gibt keine beste Farbe. Es hängt von der Notwendigkeit und oft auch vom Geschmack ab.

Auf der anderen Seite gibt es viele Möglichkeiten, über ein Dictionary in C # zu iterieren, und es gibt keinen besseren Weg. Es hängt von der Notwendigkeit und oft auch vom Geschmack ab.

Einfachster Weg

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

Wenn Sie nur den Wert benötigen (erlaubt es zu nennen) item, lesbarer als kvp.Value).

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

Wenn Sie eine bestimmte Sortierreihenfolge benötigen

Im Allgemeinen sind Anfänger über die Reihenfolge der Aufzählung eines Wörterbuchs überrascht.

LINQ bietet eine präzise Syntax, mit der Sie die Reihenfolge (und viele andere Dinge) angeben können, z.

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

Auch hier benötigen Sie möglicherweise nur den Wert. LINQ bietet auch eine übersichtliche Lösung für:

  • Iteriere direkt auf den Wert (ermöglicht es, es aufzurufen item, lesbarer als kvp.Value)
  • aber sortiert nach den Schlüsseln

Hier ist es:

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

Es gibt viele weitere praktische Anwendungsfälle, die Sie anhand dieser Beispiele durchführen können. Wenn Sie keine spezifische Bestellung benötigen, bleiben Sie einfach auf dem "einfachsten Weg" (siehe oben)!


55
2017-08-10 11:15



Ich würde sagen, foreach ist der Standardweg, obwohl es offensichtlich davon abhängt, wonach Sie suchen

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

Ist das wonach Sie suchen?


36
2017-09-26 18:22



Sie können dies auch auf großen Wörterbüchern für Multithread-Verarbeitung versuchen.

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

27
2018-06-11 13:32



Es gibt viele Möglichkeiten. Mein persönlicher Favorit ist KeyValuePair

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

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

Sie können auch die Sammlungen für Schlüssel und Werte verwenden


22
2017-09-26 18:22



Ich weiß, dass diese Frage schon viele Antworten hatte, aber ich wollte ein wenig Nachforschungen anstellen.

Das Iterieren über ein Wörterbuch kann im Vergleich zum Iterieren über etwas wie ein Array ziemlich langsam sein. In meinen Tests dauerte eine Iteration über ein Array 0,015003 Sekunden, während eine Iteration über ein Dictionary (mit der gleichen Anzahl an Elementen) 0,0365073 Sekunden dauerte, was 2,4-mal so lang ist! Obwohl ich viel größere Unterschiede gesehen habe. Zum Vergleich war eine Liste irgendwo zwischen 0,00215043 Sekunden.

Dies ist jedoch vergleichbar mit dem Vergleich von Äpfeln und Orangen. Mein Punkt ist, dass das Iterieren über Wörterbücher langsam ist.

Wörterbücher sind für Nachschlagezwecke optimiert, daher habe ich zwei Methoden entwickelt. Man macht einfach eine foreach, der andere iteriert die Schlüssel und schaut dann nach oben.

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

    return "Normal";
}

Dieser lädt die Schlüssel und iteriert stattdessen über sie (ich habe auch versucht, die Schlüssel in eine Zeichenfolge [] zu ziehen, aber der Unterschied war vernachlässigbar.

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";
}

In diesem Beispiel hat der normale foreach-Test 0.0310062 und die Schlüsselversion 0.2205441. Das Laden aller Tasten und das Iterieren über alle Lookups ist deutlich viel langsamer!

Für einen letzten Test habe ich meine Iteration zehn Mal durchgeführt, um zu sehen, ob es irgendwelche Vorteile für die Verwendung der Schlüssel gibt (zu diesem Zeitpunkt war ich nur neugierig):

Hier ist die RunTest-Methode, wenn Sie dadurch visualisieren können, was vor sich geht.

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);
}

Hier benötigte der normale foreach-Lauf 0.2820564 Sekunden (etwa zehnmal länger als eine einzelne Iteration benötigt hat - wie man es erwarten würde). Die Iteration über die Schlüssel dauerte 2,2249449 Sekunden.

Bearbeitet um hinzuzufügen: Das Lesen einiger der anderen Antworten ließ mich fragen, was passieren würde, wenn ich Dictionary statt Dictionary verwenden würde. In diesem Beispiel benötigte das Array 0,0120024 Sekunden, die Liste 0,0185037 Sekunden und das Wörterbuch 0,0465093 Sekunden. Es ist vernünftig zu erwarten, dass der Datentyp einen Unterschied dahingehend macht, wie viel langsamer das Wörterbuch ist.

Was sind meine Schlussfolgerungen??

  • Vermeiden Sie das Iterieren über ein Wörterbuch, wenn Sie können, sind sie wesentlich langsamer als das Iterieren über ein Array mit denselben Daten darin.
  • Wenn Sie sich dafür entscheiden, über ein Wörterbuch zu iterieren, versuchen Sie nicht, zu schlau zu sein, obwohl Sie langsamer arbeiten könnten, als wenn Sie die Standardmethode foreach verwenden würden.

22
2017-07-30 10:54



Sie haben unten vorgeschlagen, zu iterieren

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

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

Zu Ihrer Information, foreach funktioniert nicht, wenn der Wert vom Typ Objekt ist.


9
2017-10-28 20:49



Mit .NET Framework 4.7 man kann es benutzen Zersetzung

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

Fügen Sie hinzu, um diesen Code für niedrigere C # -Versionen zu verwenden System.ValueTuple NuGet package und schreibe irgendwo

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;
    }
}

8
2017-10-17 15:18