Lặp lại C # thông qua NameValueCollection


76

Tôi có một NameValueCollectionvà muốn lặp lại các giá trị. Hiện tại, tôi đang làm việc này, nhưng có vẻ như cần có một cách gọn gàng hơn để làm điều đó:

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

Lanhung?


3
Bạn bị gì vậy?
Ani

2
Không có gì sai với nó - chỉ là tôi nghĩ rằng tôi có thể lặp lại bằng cách sử dụng một vòng lặp. Xem xét các câu trả lời cho đến nay, điều này dường như không khả thi nếu có thể có các giá trị khóa trùng lặp.
Paul Michaels

đó là đúng, nhưng bạn có thể sử dụng bộ sưu tập khác nhau ví dụDictionary<string, List<string>>
Bóng Wizard là tiêm

Câu trả lời:


102

Bạn có thể san phẳng bộ sưu tập với Linq, nhưng nó vẫn là một foreach vòng lặp nhưng bây giờ đã ẩn hơn.

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

Dòng đầu tiên, chuyển đổi tập hợp lồng nhau thành tập hợp (không lồng nhau) của các đối tượng ẩn danh với khóagiá trị thuộc tính .

Nó được làm phẳng theo cách bây giờ nó là một khóa ánh xạ -> giá trị thay vì khóa -> tập hợp các giá trị . Dữ liệu ví dụ:

Trước:

Kiểm tra -> [Val],

Test2 -> [Val1, Val1, Val2],

Test3 -> [Val1],

Test4 -> [Val4]

Sau:

Kiểm tra -> Val,

Test2 -> Val1,

Test2 -> Val1,

Test2 -> Val2,

Test3 -> Val1,

Test4 -> Val4


3
Đã thử nghiệm và sử dụngusing System.Linq;
Julian

3
Trong trường hợp ai đó muốn biết cú pháp vb.net:Dim items = nvc.AllKeys.SelectMany(AddressOf col.GetValues, Function(k, v) New With {.key = k, .value = v})
Endy Tjahjono

2
@EndyTjahjono typo nhẹ, thay đổi "col" thành "NVP" để nó trở nênDim items = nvc.AllKeys.SelectMany(AddressOf nvp.GetValues, Function(k, v) New With {.key = k, .value = v})
Tim Partridge


Điều gì xảy ra nếu đó là một giá trị trống, làm cách nào để tôi chỉ cần thêm string.emptyvào thay thế?
Si8

83

Bạn có thể sử dụng khóa để tra cứu thay vì có hai vòng lặp:

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

19
Lưu ý rằng điều này sẽ hoạt động khác với mã của OP nếu có bất kỳ khóa nào có nhiều giá trị. Mã của bạn sẽ xuất ra "key value1, value2, value3" , trong khi mã của OP sẽ xuất ra "key value1" rồi đến "key value2" rồi đến "key value3" .
LukeH

4

Không có gì mới để xem ở đây (câu trả lời của @ Julian's +1 bởi tôi là tương đương về mặt chức năng), các bạn vui lòng di chuyển theo.


Tôi có một bộ [quá mức cần thiết cho trường hợp này nhưng có thể có liên quan] trong câu trả lời cho một câu hỏi liên quan , điều này sẽ cho phép bạn làm:

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

3
NameValueCollection không có AsEnumerable hoặc như KeyValuePairs
Luis Tellez

@Luis Tellez. Tôi biết. Văn bản cho biết tôi có một tập hợp các phương pháp mở rộng . Và nó liên kết với nó. Và phần nội dung đang gắn cờ rằng không có gì mới để xem ở đây. Điều này có làm rõ hay tôi cần giải thích lại?
Ruben Bartelink

1

Cách duy nhất tôi tìm thấy để tránh các vòng lặp lồng nhau là sử dụng Danh sách bổ sung để lưu trữ các giá trị:

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

(Yêu cầu [chỉ] .NET 2.0 trở lên)


(rõ ràng là thay thế bằng cách sử dụng SelectManynhư câu trả lời khác )
Ruben Bartelink

@Ruben true, nhưng tôi muốn để lại cái này ngay cả khi chỉ vì giá trị lịch sử cho thấy cách thực hiện điều đó với phiên bản .NET cũ. :)
Shadow Wizard đang tiêm chủng

Điều SelectManytôi gặp phải là nếu khóa có giá trị trống thì nó không thành công. Bất kỳ cách nào xung quanh nó? Cảm ơn.
Si8

@ Si8 chính xác là những gì không thành công? Về lý thuyết, chỉ cần ném một ifcâu lệnh và kiểm tra giá trị null, mặc dù nếu mã của bạn là một chữ lót, nó sẽ khiến nó khó đọc hơn nhiều.
Shadow Wizard đang tiêm chủng

Phương pháp của bạn hoạt động với null nhưng LINQ không phải là những gì tôi đã nói ... xin lỗi vì không rõ ràng.
Si8

1

Tôi nghĩ điều này đơn giản hơn:

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

HOẶC khi các phím có thể vô hiệu:

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

Thao tác này sẽ trả về cho bạn tất cả các khóa và giá trị tương ứng.


2
Không; nó sẽ không trả về các giá trị trùng lặp.
SLaks

Đây có phải là sự trùng lặp của stackoverflow.com/a/5065986/11635 trước đó mili giây không (wow!) - cá nhân tôi muốn xóa. @Slaks là pedantic, nó sẽ cung cấp các giá trị trùng lặp, chỉ bằng dấu phẩy phân tách chúng.
Ruben Bartelink
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.