C # Ітерація через NameValueCollection


76

У мене є NameValueCollection, і я хочу переглядати значення. На даний момент я роблю це, але, схоже, це повинен бути більш акуратний спосіб:

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

Є там?


3
Що поганого в тому, що у вас є?
— Ані

2
У цьому немає нічого поганого як такого - просто я думав, що мав би мати можливість ітерації за допомогою одного циклу. Переглядаючи відповіді на даний момент, здається, це неможливо, якщо можуть бути повторювані значення ключів.
— Paul Michaels

це правильно, але ви можете використовувати іншу колекцію, наприкладDictionary<string, List<string>>
— Майстер тіней вакцинує

Відповіді:


102

Ви можете згладити колекцію за допомогою Linq, але це все одно foreachцикл, але тепер більш неявний.

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

Перший рядок перетворює вкладену колекцію у (невкладену) колекцію анонімних об’єктів із ключем властивостей та значенням .

Це вирівнюється так, що тепер це ключ зіставлення -> значення замість ключа -> колекція значень . Приклад даних:

До:

Тест -> [Val],

Тест2 -> [Val1, Val1, Val2],

Тест3 -> [Val1],

Test4 -> [Val4]

Після:

Тест -> Валь,

Тест2 -> Val1,

Тест2 -> Val1,

Тест2 -> Val2,

Тест3 -> Val1,

Test4 -> Val4


3
Випробувано та використовуєтьсяusing System.Linq;
— Джуліан

3
На випадок, якщо хтось захоче знати синтаксис vb.net:Dim items = nvc.AllKeys.SelectMany(AddressOf col.GetValues, Function(k, v) New With {.key = k, .value = v})
— Endy Tjahjono

2
@EndyTjahjono легка друкарська помилка, змініть "col" на "nvp", так це стаєDim items = nvc.AllKeys.SelectMany(AddressOf nvp.GetValues, Function(k, v) New With {.key = k, .value = v})
— Тім Партрідж


Що робити, якщо це порожнє значення, як мені string.emptyзамість цього просто додати add ?
— Si8

83

Ви можете використовувати ключ для пошуку замість того, щоб мати два цикли:

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

19
Зауважте, що це буде поводитися інакше, ніж код OP, якщо є ключі з декількома значеннями. Ваш код виведе "ключ значення1, значення2, значення3" , тоді як код операційної системи виведе " ключ значення1", потім "ключ значення2", потім "ключ значення3" .
— LukeH

4

Тут нічого нового не можна побачити (відповідь @ Julian, поставлену мною +1, функціонально еквівалентна). Ви, будь ласка, рухайтесь по всьому.


У мене є [надмірний для цього випадку, але, можливо, відповідний] набір методів розширення у відповіді на відповідне запитання , яке дозволить вам зробити:

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

3
NameValueCollection не має AsEnumerable або як keyValuePairs
— Луїс

@ Луїс Теллез. Я знаю. У тексті сказано, що я маю набір методів розширення . І це посилається на нього. І основний текст стверджує, що тут нічого нового не можна побачити, будь ласка. Це пояснює чи мені потрібно повторно пояснити?
— Рубен Бартелінк,

1

Єдиний спосіб, який я знайшов, щоб уникнути вкладених циклів - використання додаткового списку для зберігання значень:

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

(Потрібен [лише] .NET 2.0 або новішої версії)


(очевидно замінено використанням, SelectManyяк і інша відповідь )
— Рубен Бартелінк

@Ruben правда, але я вважаю за краще залишити цей, навіть якщо просто для історичної цінності показує, як це зробити зі старою версією .NET. :)
— Майстер Тіней робить щеплення

Річ, з якою SelectManyя зіткнувся, полягає в тому, що якщо ключ має пусте значення, він не вдається. Будь-який спосіб обійти це? Дякую.
— Si8

@ Si8, що саме не вдається? Теоретично просто киньте ifвиписку та перевірте, чи не має значення null, хоча якщо ваш код однолінійний, це зробить його набагато менш читабельним.
— Майстер Тіней робить щеплення

Ваш метод працює з нулем, але LINQ - це не те, про що я заявляв ... вибачте за незрозуміле.
— Si8


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

АБО, коли клавіші мають нульовий статус:

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

Це поверне вам усі ключі та відповідні значення.


2
Ні; він не поверне повторюваних значень.
— Слакс

Хіба це не дубль stackoverflow.com/a/5065986/11635, який на мілісекунди раніше (вау!) - особисто я б видалив. @Slaks буде педантичним, він дасть повторювані значення, лише з комами, що розділяють їх.
— Ruben Bartelink
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.