views:

5428

answers:

6

Hi,

I want to enumerate dictionary. How i enumerate.

Thanks

+22  A: 

To enumerate a dictionary you either enumerate the values within it:

Dictionary<int, string> dic;

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

or the KeyValuePairs

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

or the keys

foreach(int key in dic.Keys)
{
    Console.WriteLine(key.ToString());
}
Ian
Or you can enumerate the keys.
strager
Indeed! Thanks for pointing that out.
Ian
I'd expect that enumerating the keys would be more common than enumerating only the values (at least it has been in my experience), since you can find the value for the key quite easily (that being the point of the dictionary).
Wedge
+8  A: 

Foreach. There are three ways: You can enumerate over the Keys property, over the Values property or over the dictionary itself which is an enumerator of KeyValuePair<TKey, TValue>.

Matthias

Mudu
A: 

Hi lan,

Suppose i use foreach() for dictionay enumeration . I can't update value/key inside foreach(). So i want some other methos

Thanks,

Ravi
+3  A: 

In answer to the problem "I can't update value/key inside foreach()", you cannot modify a collection while enumerating it. I would approach this by making a copy of the Keys collection:

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

//...fill the dictionary

int[] keys = dic.Keys.ToArray();
foreach (int i in keys)
{
    dic.Remove(i);
}
spender
No need for .ToArray() AFAIK. .Keys returns an IEnumerable.
strager
sure, but if the dictionary is altered in the loop, what happens to that enumeration? it changes, surely?
spender
I wouldn't have thought so. The dic.Keys will return an IEnumerable<int> in this case, which will be all values. If you were to just use the IEnumerator<int> instead then this might be the case.
Ian
changing the line: foreach(int i in keys)to foreach(int i in dic.keys)throws and InvalidOperationException, "Collection was modified; enumeration operation may not execute."Making a copy, as above does not fail in this way.
spender
A: 

Indeed as Spender pointed out you can't modify the thing you are enumerating over. You could do one of two things:

1) Follow Spender's approach by creating a copy.

List<int> keys = new List<int>();

foreach(KeyValuePair<int,String> kvp in dic)
{
   if(needToRemoveKey)
      keys.Add(kvp.Key);
}

for(int i = 0; i < keys.Count; i++)
{
   //dic.Remove(keys[i]);
   //dic[keys[i]] = newValue;

   //etc 
}

2) Or a bit harder use a for loop and decrement the counter (but you can run into problems more easily so I won't post any code for this because I don't want to encourage you to do it).

Ian
A: 

I just answered the same (updated) question for lists, so here's the same thing for dictionaries.

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

Note that we have to do the updates outside the loop, so we aren't modifying the dictionary as we enumerate it. Also this detects clashes caused by making two keys the same - it will throw (due to the use of Add).

Example - make all keys lowercase and trim all values, with a Dictionary<string, string>:

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

If the keys are not unique when made lowercase, this will throw.

Daniel Earwicker