2009-03-24 36 views
21

Làm cách nào để liệt kê một từ điển?Điều tra từ điển trong C#

Giả sử tôi sử dụng foreach() để liệt kê dictionay. Tôi không thể cập nhật cặp khóa/giá trị bên trong foreach(). Vì vậy, tôi muốn một số phương pháp khác.

Trả lời

75

Để liệt kê một cuốn từ điển bạn hoặc liệt kê các giá trị bên trong nó:

Dictionary<int, string> dic; 

foreach(string s in dic.Values) 
{ 
    Console.WriteLine(s); 
} 

hoặc KeyValuePairs

foreach(KeyValuePair<int, string> kvp in dic) 
{ 
    Console.WriteLine("Key : " + kvp.Key.ToString() + ", Value : " + kvp.Value); 
} 

hoặc các phím

foreach(int key in dic.Keys) 
{ 
    Console.WriteLine(key.ToString()); 
} 

Nếu bạn muốn cập nhật các mục trong từ điển bạn cần phải làm như vậy hơi khác, bởi vì bạn không thể cập nhật cá thể trong khi liệt kê. Những gì bạn sẽ cần phải làm là liệt kê một bộ sưu tập khác nhau mà không được cập nhật, như vậy:

Dictionary<int, string> newValues = new Dictionary<int, string>() { 1, "Test" }; 
foreach(KeyValuePair<int, string> kvp in newValues) 
{ 
    dic[kvp.Key] = kvp.Value; // will automatically add the item if it's not there 
} 

Để xoá các mục, làm như vậy trong một cách tương tự, liệt kê các bộ sưu tập các mặt hàng chúng tôi muốn loại bỏ khá so với chính từ điển.

List<int> keys = new List<int>() { 1, 3 }; 
foreach(int key in keys) 
{ 
    dic.Remove(key); 
} 
+0

Hoặc bạn có thể liệt kê các phím. – strager

+0

Thật vậy! Cảm ơn bạn đã chỉ ra điều đó. – Ian

+2

Tôi hy vọng rằng việc liệt kê các phím sẽ phổ biến hơn chỉ liệt kê các giá trị (ít nhất là theo kinh nghiệm của tôi), vì bạn có thể tìm thấy giá trị cho khóa khá dễ dàng (đó là điểm của từ điển). – Wedge

8

Foreach. Có ba cách: Bạn có thể liệt kê trên thuộc tính Keys, qua thuộc tính Values hoặc trên chính từ điển mà là một điều tra viên của KeyValuePair<TKey, TValue>.

9

Trong câu trả lời cho vấn đề "Tôi không thể cập nhật giá trị/khóa bên trong foreach()", bạn không thể sửa đổi bộ sưu tập khi liệt kê nó. Tôi sẽ tiếp cận điều này bằng cách tạo một bản sao của bộ sưu tập Keys:

Dictionary<int,int> dic=new Dictionary<int, int>(); 

//...fill the dictionary 

int[] keys = dic.Keys.ToArray(); 
foreach (int i in keys) 
{ 
    dic.Remove(i); 
} 
+0

Không cần .ToArray() AFAIK. .Keys trả về một IEnumerable. – strager

+1

chắc chắn, nhưng nếu từ điển bị thay đổi trong vòng lặp, điều gì sẽ xảy ra với điều tra đó? nó thay đổi, chắc chắn? – spender

+0

Tôi sẽ không nghĩ như vậy. Các dic.Keys sẽ trả về một số IE2 có thể đếm được là trong trường hợp này, sẽ là tất cả các giá trị. Nếu bạn chỉ cần sử dụng IEnumerator thay vào đó thì đây có thể là trường hợp. – Ian

2

Tôi vừa trả lời cùng một câu hỏi (cập nhật) cho danh sách, vì vậy đây là điều tương tự đối với từ điển.

public static void MutateEach(this IDictionary<TKey, TValue> dict, Func<TKey, TValue, KeyValuePair<TKey, TValue>> mutator) 
{ 
    var removals = new List<TKey>(); 
    var additions = new List<KeyValuePair<TKey, TValue>>(); 

    foreach (var pair in dict) 
    { 
     var newPair = mutator(pair.Key, pair.Value); 
     if ((newPair.Key != pair.Key) || (newPair.Value != pair.Value)) 
     { 
      removals.Add(pair.Key); 
      additions.Add(newPair); 
     } 
    } 

    foreach (var removal in removals) 
     dict.Remove(removal); 

    foreach (var addition in additions) 
     dict.Add(addition.Key, addition.Value); 
} 

Lưu ý rằng chúng tôi phải thực hiện cập nhật bên ngoài vòng lặp, vì vậy chúng tôi không sửa đổi từ điển khi chúng tôi liệt kê từ điển. Ngoài ra, điều này phát hiện xung đột gây ra bằng cách làm cho hai phím giống nhau - nó sẽ ném (do việc sử dụng Add).

Ví dụ - làm cho tất cả các phím chữ thường và cắt tất cả các giá trị, với một Dictionary<string, string>:

myDict.MutateEach(key => key.ToLower(), value => value.Trim()); 

Nếu các phím không duy nhất khi làm chữ thường, điều này sẽ ném.