C # Durch NameValueCollection iterieren


76

Ich habe eine NameValueCollectionund möchte die Werte durchlaufen. Momentan mache ich das, aber es scheint, als gäbe es einen besseren Weg, dies zu tun:

NameValueCollection nvc = new NameValueCollection();
nvc.Add("Test", "Val1");
nvc.Add("Test2", "Val1");
nvc.Add("Test2", "Val1");
nvc.Add("Test2", "Val2");
nvc.Add("Test3", "Val1");
nvc.Add("Test4", "Val4");

foreach (string s in nvc)
    foreach (string v in nvc.GetValues(s))
        Console.WriteLine("{0} {1}", s, v);

Console.ReadLine();

Gibt es?


3
Was ist los mit dem, was du hast?
Ani

2
Es ist an sich nichts falsch daran - nur, dass ich dachte, ich sollte in der Lage sein, mit einer einzigen Schleife zu iterieren. Bei Betrachtung der bisherigen Antworten scheint dies nicht möglich zu sein, wenn möglicherweise doppelte Schlüsselwerte vorhanden sind.
Paul Michaels

Das ist richtig, aber Sie können verschiedene Sammlungen verwenden, zBDictionary<string, List<string>>
Shadow Wizard ist Ear For You

Antworten:


102

Sie können die Sammlung mit Linq reduzieren, aber es ist immer noch eine foreachSchleife, aber jetzt impliziter.

var items = nvc.AllKeys.SelectMany(nvc.GetValues, (k, v) => new {key = k, value = v});
foreach (var item in items)
    Console.WriteLine("{0} {1}", item.key, item.value);

Die erste Zeile, wandelt die verschachtelte Sammlung in eine (nicht-verschachtelte) Sammlung von anonymen Objekte mit den Eigenschaften Schlüssel und Wert .

Es ist so abgeflacht, dass es jetzt ein Zuordnungsschlüssel ist -> Wert anstelle von Schlüssel -> Sammlung von Werten . Die Beispieldaten:

Vor:

Test -> [Val],

Test2 -> [Val1, Val1, Val2],

Test3 -> [Val1],

Test4 -> [Val4]

Nach:

Test -> Val,

Test2 -> Val1,

Test2 -> Val1,

Test2 -> Val2,

Test3 -> Val1,

Test4 -> Val4


3
Getestet und verwendetusing System.Linq;
Julian

3
Für den Fall, dass jemand die vb.net-Syntax kennen möchte:Dim items = nvc.AllKeys.SelectMany(AddressOf col.GetValues, Function(k, v) New With {.key = k, .value = v})
Endy Tjahjono

2
@EndyTjahjono leichter Tippfehler, ändern Sie "col" in "nvp", so dass es wirdDim items = nvc.AllKeys.SelectMany(AddressOf nvp.GetValues, Function(k, v) New With {.key = k, .value = v})
Tim Partridge


Was ist, wenn es sich um einen leeren Wert handelt string.empty? Wie kann ich stattdessen nur hinzufügen ?
Si8

83

Sie können den Schlüssel für die Suche verwenden, anstatt zwei Schleifen zu haben:

foreach (string key in nvc)
{
    Console.WriteLine("{0} {1}", key, nvc[key]);
}

19
Beachten Sie, dass sich dies anders als der OP-Code verhält, wenn Schlüssel mit mehreren Werten vorhanden sind. Ihr Code gibt "Schlüsselwert1, Wert2, Wert3" aus , während der OP-Code "Schlüsselwert1", dann "Schlüsselwert2" und dann "Schlüsselwert3" ausgibt .
LukeH

4

Hier gibt es nichts Neues zu sehen (@ Julians + 1 Antwort von mir ist funktional gleichwertig), Sie gehen bitte weiter.


Ich habe einen [Overkill für diesen Fall, aber möglicherweise relevanten] Satz von Erweiterungsmethoden in einer Antwort auf eine verwandte Frage , mit der Sie Folgendes tun können:

foreach ( KeyValuePair<string,string> item in nvc.AsEnumerable().AsKeyValuePairs() )
    Console.WriteLine("{0} {1}", item.key, item.value);

3
NameValueCollection hat nicht AsEnumerable oder als keyValuePairs
Luis Tellez

@ Luis Tellez. Ich weiß. Der Text sagt, ich habe eine Reihe von Erweiterungsmethoden . Und es verlinkt darauf. Und der Text zeigt an, dass es hier bitte nichts Neues zu sehen gibt. Klärt dies oder muss ich es noch einmal erklären?
Ruben Bartelink

1

Die einzige Möglichkeit, die verschachtelten Schleifen zu vermeiden, besteht darin, zusätzliche Werte zum Speichern der Werte zu verwenden:

List<string> arrValues = new List<string>();
for (int i = 0; i < nvc.Count; i++)
    arrValues.AddRange(nvc.GetValues(i));
foreach (string value in arrValues)
    Console.WriteLine(value);

(Benötigt [nur] .NET 2.0 oder höher)


(offensichtlich ersetzt durch Verwendung SelectManywie die andere Antwort )
Ruben Bartelink

@Ruben wahr, aber ich ziehe es vor, dieses zu belassen, auch wenn es nur um den historischen Wert geht, der zeigt, wie man das mit der alten .NET-Version macht. :)
Shadow Wizard ist Ear For You

Die Sache, auf die SelectManyich gestoßen bin, ist, wenn der Schlüssel einen Wert hat, der leer ist, schlägt er fehl. Irgendein Weg darum herum? Vielen Dank.
Si8

@ Si8 was genau scheitert? Theoretisch werfen Sie einfach eine ifAnweisung und prüfen Sie, ob sie null ist. Wenn Ihr Code jedoch einzeilig ist, wird er viel weniger lesbar.
Schatten-Assistent ist Ohr für Sie

Ihre Methode funktioniert mit der Null, aber der LINQ ist nicht das, was ich angegeben habe ... Entschuldigung, nicht klar.
Si8

1

Ich denke das ist einfacher:

For i As Integer = 0 To nvc.Count - 1
   Console.Write("No", "Key", "Value")
   Console.Write(i, nvc.GetKey(i), nvc.Get(i))
Next

0
var enu = myNameValueCollection.GetEnumerator();
while (enu.MoveNext())
{
    string key = (string)enu.Current;
    string value = myNameValueCollection[key];
}

ODER wenn Schlüssel nullbar sind:

for (int i = 0; i < myNameValueCollection.Count; i++)
{
    string key = myNameValueCollection.GetKey(i);
    string value = myNameValueCollection.Get(i);
}

-2
foreach ( string key in nvc.Keys )
   Console.WriteLine("{0} {1}", key, nvc[key]);

Dadurch erhalten Sie alle Schlüssel und die entsprechenden Werte zurück.


2
Nein; Es werden keine doppelten Werte zurückgegeben.
SLaks

Ist das nicht ein Dup von stackoverflow.com/a/5065986/11635, der Millisekunden früher ist (wow!) - persönlich würde ich löschen. @Slaks um pedantisch zu sein, gibt es die doppelten Werte, nur durch Kommas getrennt.
Ruben Bartelink
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.