loop - c# keyvaluepair




Wie kann ich ein Wörterbuch am besten durchlaufen? (17)

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


Ab C # 7 können Sie Objekte in Variablen dekonstruieren. Ich glaube, dass dies der beste Weg ist, ein Wörterbuch zu durchlaufen.

Beispiel:

Erstellen Sie eine Erweiterungsmethode auf KeyValuePair<TKey, TVal> , die diese dekonstruiert:

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

Durchlaufen Sie jedes Dictionary<TKey, TVal> auf folgende Weise

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

Die Standardmethode zum Durchlaufen eines Dictionarys gemäß der offiziellen Dokumentation zu MSDN ist:

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

Es gibt viele Möglichkeiten. Mein persönlicher Favorit ist von 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 Sammlung von Schlüsseln und Werten verwenden


Fügen Sie in C # 7 diese Erweiterungsmethode zu jedem Projekt Ihrer Lösung hinzu:

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


Und verwenden Sie diese einfache Syntax

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


Oder diese hier, wenn Sie es vorziehen

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


An die Stelle des Traditionellen

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

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


Die Erweiterungsmethode wandelt das IDictionary<TKey, TValue> Ihres IDictionary<TKey, TValue> in ein stark typisiertes tuple , sodass Sie diese neue komfortable Syntax verwenden können.

Es konvertiert -just- die erforderlichen Wörterbucheinträge in tuples Das gesamte Wörterbuch wird NICHT in tuples konvertiert. Daher gibt es keine Leistungsprobleme.

Das Aufrufen der Erweiterungsmethode zum Erstellen eines tuple im Vergleich zur direkten Verwendung von KeyValuePair ist mit nur geringen Kosten verbunden. KeyValuePair sollte KEIN Problem sein, wenn Sie den KeyValuePair -Eigenschaften Key und Value sowieso neuen Loop-Variablen zuweisen.

In der Praxis ist diese neue Syntax für die meisten Fälle sehr gut geeignet, mit Ausnahme von Szenarien mit extrem hoher Leistung, bei denen Sie immer noch die Möglichkeit haben, sie an dieser Stelle nicht zu verwenden.

Schauen Sie sich das an: MSDN Blog - Neue Funktionen in C # 7


Ich habe eine Erweiterung geschrieben, um ein Wörterbuch zu durchlaufen.

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

Dann kannst du anrufen

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

Ich schätze, dass diese Frage bereits viele Antworten hatte, aber ich wollte etwas Forschung einbringen.

Das Durchlaufen eines Wörterbuchs kann relativ langsam sein, verglichen mit dem Durchlaufen eines Arrays. In meinen Tests dauerte eine Iteration über ein Array 0.015003 Sekunden, wohingegen eine Iteration über ein Wörterbuch (mit der gleichen Anzahl von Elementen) 0.0365073 Sekunden dauerte, also 2,4 mal so lang! Obwohl ich viel größere Unterschiede gesehen habe. Zum Vergleich lag eine Liste irgendwo dazwischen bei 0,00215043 Sekunden.

Dies ist jedoch vergleichbar mit Äpfeln und Orangen. Mein Punkt ist, dass das Durchlaufen von Wörterbüchern langsam ist.

Wörterbücher sind für Suchvorgänge optimiert. Deshalb habe ich zwei Methoden entwickelt. Der eine führt einfach eine foreach durch, der andere iteriert die Schlüssel und schaut dann auf.

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

    return "Normal";
}

Dieses lädt die Schlüssel und iteriert stattdessen über sie (ich habe auch versucht, die Schlüssel in einen String [] 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";
}

Bei diesem Beispiel wurden für den normalen foreach-Test 0,0310062 und für die Schlüsselversion 0,2205441 verwendet. Das Laden aller Schlüssel und das Durchlaufen aller Suchvorgänge ist deutlich langsamer!

Für einen abschließenden Test habe ich zehnmal meine Iteration durchgeführt, um zu sehen, ob die Verwendung der Tasten hier Vorteile hat (bis jetzt war ich nur neugierig):

Hier ist die RunTest-Methode, wenn Sie sich anschaulich machen, was los ist.

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 dauerte der normale Foreach-Lauf 0,2820564 Sekunden (etwa zehnmal länger als eine einzelne Iteration - wie Sie es erwarten würden). Die Iteration über die Tasten dauerte 2.2249449 Sekunden.

Zum Hinzufügen hinzugefügt: Nachdem ich einige der anderen Antworten gelesen hatte, fragte ich mich, was passieren würde, wenn ich Dictionary anstelle von Dictionary verwende. In diesem Beispiel dauerte das Array 0.0120024 Sekunden, die Liste 0.0185037 Sekunden und das Wörterbuch 0,0465093 Sekunden. Man kann davon ausgehen, dass der Datentyp einen Unterschied macht, wie viel langsamer das Wörterbuch ist.

Was sind meine Schlussfolgerungen ?

  • Vermeiden Sie das Durchlaufen eines Wörterbuchs, wenn Sie können, da diese wesentlich langsamer sind als ein Array mit den gleichen Daten.
  • Wenn Sie sich entscheiden, ein Wörterbuch zu durchlaufen, sollten Sie nicht zu schlau sein, auch wenn Sie langsamer sind, als Sie die Standardmethode foreach verwenden.

Ich werde den Vorteil von .NET 4.0+ nutzen und eine aktualisierte Antwort auf die ursprünglich akzeptierte Antwort geben:

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

Ich wollte nur 2 Cent hinzufügen, da sich die meisten Antworten auf die foreach-Schleife beziehen. Bitte schauen Sie sich den folgenden Code an:

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

Obwohl dies einen zusätzlichen Aufruf von ".ToList ()" hinzufügt, kann es zu einer geringfügigen Leistungsverbesserung kommen (wie hier bei foreach vs someList.Foreach () {} ) hervorgehoben, insbesondere wenn mit großen Wörterbüchern gearbeitet wird und parallel ausgeführt wird Option / hat überhaupt keinen Effekt.

Beachten Sie auch, dass Sie der 'Value'-Eigenschaft innerhalb einer foreach-Schleife keine Werte zuweisen können. Auf der anderen Seite können Sie auch den 'Key' manipulieren, wodurch Sie möglicherweise zur Laufzeit in Schwierigkeiten geraten.

Wenn Sie nur Schlüssel und Werte "lesen" möchten, können Sie auch IEnumerable.Select () verwenden.

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

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

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

Kommt drauf an, ob Sie nach den Schlüsseln oder den Werten suchen ...

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

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

FYI, foreach funktioniert nicht, wenn der Wert vom Typ object ist.


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

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

Wenn Sie beispielsweise die Wertesammlung standardmäßig durchlaufen möchten, können Sie IEnumerable <> implementieren, wobei T der Typ des Wertobjekts im Wörterbuch ist und "this" ein Dictionary ist.

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


zusätzlich zu den höchstrangigen Beiträgen, bei denen eine Diskussion zwischen der Verwendung stattfindet

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

oder

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

Am vollständigsten ist Folgendes, da Sie den Wörterbuchtyp bei der Initialisierung sehen können, kvp ist 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
}

Dictionary <TKey, TValue> Dies ist eine generische Collection-Klasse in c # und speichert die Daten im Schlüsselwertformat. Der Schlüssel muss eindeutig sein und darf nicht null sein, wohingegen der Wert doppelt und null sein kann. Jedes Element im Wörterbuch ist Wird als KeyValuePair <TKey, TValue> -Struktur behandelt, die einen Schlüssel und seinen Wert darstellt. Daher sollten wir den Elementtyp KeyValuePair <TKey, TValue> während der Iteration des Elements verwenden. Unten ist das Beispiel.

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

var dictionary = new Dictionary<string, int>
{
    { "Key", 12 }
};

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




loops