Ich habe ein paar verschiedene Möglichkeiten, über ein Wörterbuch in C# zu iterieren gesehen. Gibt es eine Standardmethode?
Antworten
Zu viele Anzeigen?Die beste Antwort ist natürlich: Überlegen Sie, ob Sie eine geeignetere Datenstruktur als ein Wörterbuch verwenden können, wenn Sie vorhaben, darüber zu iterieren - wie Vikas Gupta bereits zu Beginn der Diskussion unter der Frage erwähnte. Aber dieser Diskussion wie auch diesem ganzen Thread fehlt es noch an überraschend guten Alternativen. Eine davon ist:
SortedList<string, string> x = new SortedList<string, string>();
x.Add("key1", "value1");
x.Add("key2", "value2");
x["key3"] = "value3";
foreach( KeyValuePair<string, string> kvPair in x )
Console.WriteLine($"{kvPair.Key}, {kvPair.Value}");
Warum könnte man argumentieren, dass die Iteration über ein Wörterbuch (z. B. durch foreach(KeyValuePair<,>)) einen Codegeruch hat?
Ein Grundprinzip des Clean Coding: " Absicht ausdrücken! " Robert C. Martin schreibt in "Clean Code": "Die Wahl von Namen, die die Absicht verraten". Offensichtlich ist die Namensgebung allein zu schwach. " Mit jeder Kodierungsentscheidung die Absicht ausdrücken (offenbaren)" drückt es besser aus.
Ein verwandtes Prinzip ist " Das Prinzip der geringsten Überraschung " (= Grundsatz der geringsten Verwunderung ).
Warum ist dies mit der Iteration über ein Wörterbuch verbunden? Die Wahl eines Wörterbuchs bringt die Absicht zum Ausdruck, eine Datenstruktur zu wählen, die in erster Linie für das Auffinden von Daten nach Schlüsseln gedacht ist . Heutzutage gibt es so viele Alternativen in .NET, wenn Sie durch Schlüssel/Wert-Paare iterieren wollen, dass Sie etwas anderes wählen könnten.
Außerdem: Wenn man über etwas iteriert, muss man etwas darüber aussagen, wie die Elemente geordnet sind (werden sollen) und wie man erwartet, dass sie geordnet sind! Obwohl die bekannten Implementierungen von Dictionary die Schlüsselsammlung in der Reihenfolge der hinzugefügten Elemente sortieren- AFAIK, Dictionary hat keine gesicherte Spezifikation über die Reihenfolge (oder doch?).
Aber was sind die Alternativen?
TLDR:
SortierteListe : Wenn Ihre Sammlung nicht zu groß wird, wäre eine einfache Lösung die Verwendung von SortedList<,>, die Ihnen auch eine vollständige Indizierung von Schlüssel/Wert-Paaren bietet.
Microsoft hat einen langen Artikel über die Erwähnung und Erläuterung passender Sammlungen:
Verschlüsselte Sammlung
Um nur die wichtigsten zu nennen: KeyedCollection <,> und SortedDictionary<,> . SortedDictionary <,> ist etwas schneller als SortedList, wenn es nur um das Einfügen geht, wenn es groß wird, aber es fehlt die Indizierung und wird nur benötigt, wenn O(log n) für das Einfügen gegenüber anderen Operationen bevorzugt wird. Wenn Sie wirklich O(1) für das Einfügen benötigen und dafür eine langsamere Iteration in Kauf nehmen, müssen Sie bei einem einfachen Dictionary<,> bleiben. Offensichtlich gibt es keine Datenstruktur, die für jede mögliche Operation die schnellste ist
Zusätzlich gibt es ImmutableSortedDictionary <,>.
Und wenn eine Datenstruktur nicht genau das ist, was Sie brauchen, dann leiten Sie von Dictionary<,> oder sogar von der neuen ConcurrentDictionary <,> und fügen Sie explizite Iterations-/Sortierfunktionen hinzu!
Ich wollte nur meine 2 Cent hinzufügen, da sich die meisten Antworten auf die foreach-Schleife beziehen. Schauen Sie sich bitte 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 dadurch ein zusätzlicher Aufruf von '.ToList()' erfolgt, kann es eine leichte Leistungsverbesserung geben (wie hier beschrieben) foreach vs someList.Foreach(){} ), vor allem, wenn man mit großen Wörterbüchern arbeitet und eine parallele Ausführung keine Option ist/keine Auswirkung haben wird.
Bitte beachten Sie auch, dass Sie der Eigenschaft "Value" innerhalb einer foreach-Schleife keine Werte zuweisen können. Andererseits können Sie auch den "Key" manipulieren, was zur Laufzeit zu Problemen führen kann.
Wenn Sie nur Schlüssel und Werte "lesen" wollen, können Sie auch IEnumerable.Select() verwenden.
var newProductPrices = myProductPrices.Select(kvp => new { Name = kvp.Key, Price = kvp.Value * 1.15 } );
Zusätzlich zu den hochrangigen Stellen, an denen eine Diskussion zwischen
foreach(KeyValuePair<string, string> entry in myDictionary)
{
// do something with entry.Value or entry.Key
}
o
foreach(var entry in myDictionary)
{
// do something with entry.Value or entry.Key
}
am vollständigsten ist die folgende, weil man den Wörterbuchtyp aus der Initialisierung erkennen kann, 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
}
- See previous answers
- Weitere Antworten anzeigen
92 Stimmen
@VikasGupta Was würden Sie vorschlagen, um etwas mit einer Sammlung von Schlüssel-Wert-Paaren zu tun, wenn Sie nicht wissen, wie die Schlüssel lauten werden?
11 Stimmen
@nasch:
myDictionary.Keys
erhalten Sie eine Sammlung, die die Schlüssel inmyDictionary
.33 Stimmen
@displayName Wenn Sie etwas mit jedem Schlüssel-Wert-Paar machen wollen, aber keinen Verweis auf die Schlüssel haben, um die Werte nachzuschlagen, würden Sie über das Wörterbuch iterieren, richtig? Ich wollte nur darauf hinweisen, dass es Fälle geben kann, in denen man das tun möchte, obwohl Vikas behauptet, dass dies in der Regel eine falsche Verwendung ist.
48 Stimmen
Die Behauptung, es handele sich um eine falsche Verwendung, impliziert, dass es eine bessere Alternative gibt. Was ist das für eine Alternative?
71 Stimmen
VikasGupta liegt falsch, das kann ich nach vielen Jahren hochleistungsfähiger C#- und C++-Programmierung in nicht-theoretischen Szenarien bestätigen. Es gibt tatsächlich häufige Fälle, in denen man ein Wörterbuch erstellt, eindeutige Schlüssel-Wert-Paare speichert und dann über diese Werte iteriert, die nachweislich eindeutige Schlüssel innerhalb der Sammlung haben. Die Erstellung weiterer Sammlungen ist ein wirklich ineffizienter und kostspieliger Weg, um die Iteration von Wörterbüchern zu vermeiden. Bitte geben Sie eine gute Alternative als Antwort auf die Frage an, um Ihren Standpunkt zu verdeutlichen, ansonsten ist Ihr Kommentar ziemlich unsinnig.
3 Stimmen
Auch zur Fehlersuche und um herauszufinden, was in Ihrem Wörterbuch steht, wenn etwas schief läuft. Dies ist sehr hilfreich
13 Stimmen
VikasGupta hat zu 100 % recht. Wenn Sie " eine Sammlung von Schlüssel-Werte-Paaren "und nicht wissen, was sie damit tun sollen, können Sie buchstäblich es in eine
ICollection<KeyValuePair>
(Einfachste Umsetzung:List
). Und wenn Sie sich mit " leistungsstarke Programmierung ", dann sollten Sie wissen, dass Das Einzige, was Wörterbücher schneller können, ist das Nachschlagen eines Eintrags über einen Schlüssel. - das Hinzufügen von Artikeln ist langsamer und das Iterieren über ein Wörterbuch kann leicht doppelt so lange dauern wie das Iterieren über eine Liste .0 Stimmen
Es gibt drei weitere Möglichkeiten, dies zu tun: 1- for Loop 2- Parallel Enumerable.ForAllMethod 3- String.Join Ein Beispiel für den Code finden Sie unter diesem Link: techiedelight.com/iterate-over-dictionary-csharp
1 Stimmen
Ich schätze, dass die Umwandlung eines Wörterbuchs in eine Liste (auch mit LINQ) eine Iteration erfordert. Oder was, wenn Sie eine Methode für jedes Element im Wörterbuch aufrufen müssen?
1 Stimmen
@MateenUlhaq Ich denke, dass Sie die Frage zu sehr verkürzt haben. Jetzt ( 5. Überarbeitung ) ist es fast eine Paraphrase des Titels, ohne jeden zusätzlichen Kontext. Ich stimme dafür, zur vorherigen Version zurückzukehren.
1 Stimmen
@TheodorZoulias Der Kontext wird wahrscheinlich nicht benötigt, damit die Frage funktioniert, da "Was ist der beste Weg / Standard"-Fragen normalerweise als Off-Topic angesehen werden, aber ich habe sie umgewandelt.