3

I use this:

foreach(KeyValuePair<String,String> entry in MyDic)
  {
      // do something with entry.Value or entry.Key

  }

The problem is that I can't change the value of entry.Value or entry.Key

My question is that how can i change the value or key when looping through a dictionary? And, does dictionary allow duplicated key? And if yes, how can we avoid ? Thank you

Dulini Atapattu
  • 2,735
  • 8
  • 33
  • 47
Xitrum
  • 7,765
  • 26
  • 90
  • 126

5 Answers5

7

You cannot change the value of a dictionary entry while looping through the items in the dictionary, although you can modify a property on the value if it's an instance of a reference type.

For example,

public class MyClass 
{
    public int SomeNumber { get; set;}
}

foreach(KeyValuePair<string, MyClass> entry in myDict)
{
    entry.Value.SomeNumber = 3; // is okay
    myDict[entry.Key] = new MyClass(); // is not okay
}

Trying to modify a dictionary (or any collection) while looping through its elements will result in an InvalidOperationException saying the collection was modified.

To answer your specific questions,

My question is that how can i change the value or key when looping through a dictionary?

The approach to both will be pretty much the same. You can either loop over a copy of the dictionary as Anthony Pengram said in his answer, or you can loop once through all the items to figure out which ones you need to modify and then loop again through a list of those items:

List<string> keysToChange = new List<string>();
foreach(KeyValuePair<string, string> entry in myDict)
{
    if(...) // some check to see if it's an item you want to act on
    {
        keysToChange.Add(entry.Key);
    }
}

foreach(string key in keysToChange)
{
   myDict[key] = "new value";

   // or "rename" a key
   myDict["new key"] = myDict[key];
   myDict.Remove(key);
}

And, does dictionary allow duplicated key? And if yes, how can we avoid ?

A dictionary does not allow duplicate keys. If you want a collection of <string, string> pairs that does, check out NameValueCollection.

Community
  • 1
  • 1
Adam Lear
  • 38,111
  • 12
  • 81
  • 101
  • can an iterator solve that problem, like an iterator of a map in java? – Xitrum Jun 29 '11 at 03:37
  • @user552279 If I recall correctly, `foreach` invokes an iterator behind the scenes and the assumption is that the collection has to stay the same. There's an explanation for that [here](http://stackoverflow.com/questions/4536090/collection-was-modified-enumeration-operation-may-not-execute-why). Anthony's answer will work cause it creates a copy of your dictionary that you can iterate over and then modify the original collection. – Adam Lear Jun 29 '11 at 03:47
6

Updating the dictionary in the loop is going to be a problem, as you cannot modify the dictionary as it is being enumerated. However, you can work around this pretty easily by converting the dictionary to a list of KeyValuePair<> objects. You enumerate that list, and then you can modify the dictionary.

foreach (var pair in dictionary.ToList())
{
    // to update the value
    dictionary[pair.Key] = "Some New Value";

    // or to change the key => remove it and add something new
    dictionary.Remove(pair.Key);
    dictionary.Add("Some New Key", pair.Value);
}

For the second part, the key in a dictionary must be unique.

Anthony Pegram
  • 123,721
  • 27
  • 225
  • 246
  • 1
    @user, your comment "why can't I see ToList()" -> This is part of Linq, which is available in C# 3+. If you are using such a version, you can add a `using System.Linq;` statement to your code file (also assumes you have a reference in your project to System.Core.dll, which is referenced by default in new projects). – Anthony Pegram Jun 29 '11 at 04:11
0

KeyValuePair's Key and value are read only. But you can change a value like that:

dictionary[key].Value = newValue;

But if you want to change the key, you will have to remove/add a key.

And no, a Dictionary does not allow duplicate keys, it will throw an ArgumentException.

Jean-Philippe Leclerc
  • 6,713
  • 5
  • 43
  • 66
0

You cannot modify keys while enumerating them.

One method I use for changes to the collection while enumerating them is that I do break; out of the foreach loop when a match is found and item is modified, and am restarting the whole enumeration all over again. That's one way of handling it...

No, Dictionary can't have duplicate keys. If you want something that will sort by key and allow duplicates, you should use some other data structure.

Daniel Mošmondor
  • 19,718
  • 12
  • 58
  • 99
-2

You can do this like

for (int i = 0; i < MyDic.Count; i++)
{
    KeyValuePair<string, string> s = MyDic.ElementAt(i);
    MyDic.Remove(s.Key);
    MyDic.Add(s.Key, "NewValue");
}

And Dictionary doesn't allow duplicates

Anuraj
  • 18,859
  • 7
  • 53
  • 79
  • Depending on the implementation underneath, modifying the collection while enumerating could produce undesirable results... – jjxtra Jun 29 '11 at 03:35
  • 1
    @Anuraj That will throw an InvalidOperationException. – Adam Lear Jun 29 '11 at 03:41
  • @Anuraj Unfortunately that's also potentially problematic. The order of elements in a dictionary isn't guaranteed, so you could be adding new elements and then either processing them again when you shouldn't or not processing them when you should, depending on what "index" they end up at. – Adam Lear Jun 29 '11 at 03:57