murmansk
murmansk

Reputation: 845

Iterating over dictionay inside dictionary

I am try to iterate over a dictionary Dictionary<uint,Dictionary<uint,uint>> myDict.

I want to change value of internal dictionary.

When I use:

foreach(var item in myDict)
{
    foreach(var rt in item)

I get the error:

Severity Code Description Project File Line Suppression State Error CS1579 foreach statement cannot operate on variables of type 'KeyValuePair<uint, Dictionary<uint, uint>>' because 'KeyValuePair<uint, Dictionary<uint, uint>>' does not contain a public instance definition for 'GetEnumerator' SparrowView

Why can't I enumerate inside?

Upvotes: 3

Views: 160

Answers (3)

Discord expert
Discord expert

Reputation: 178

Please try using item.Value.

As you are currently iterating over both uints and the dictionary, not only the dictionary.

Upvotes: 5

Caius Jard
Caius Jard

Reputation: 74605

If you're looking for a particular key in the inner dictionary it might make more sense to you to look through the keys collection and address your dictionaries by key:

foreach(var outerKey in myDict.Keys)
{
   foreach(var innerKey in myDict[outerKey].Keys)
   {
     if(innerKey == 3)
       ...
   }
}

Alternatively, if you iterate a dictionary directly you get a keyvaluepair, so you have to keep straight in your mind the difference between a key (uint) and a value (a dictionary in your outer, a uint in your inner)

foreach(var outerKvp in myDict) //foreaching the outer dictionary gives a keyvaluepair, the value of which is a dictionary
{
   foreach(var innerKvp in outerKvp.Value) //outerKvp.Value is a Dictionary<uint,uint), foreaching it will again give you a keyvaluepair, this time for the inner dictionary. the value this time is a uint
   {
     if(innerKvp.Key == 3)
       ...
   }
}

Also bear in mind if you're looking to modify either of these you can't do it inside a for loop because you can't modify a dictionary you're enumerating over. In such cases it might be better to just use ContainsKey:

//for example if you know the outer key
if(myDict.ContainsKey(1) && myDict[1].ContainsKey(3))
    myDict[1][3] = 4;

//or if you don't know the outer key
foreach(var outerKey in myDict.Keys)
{
   if(myDict[outerKey].ContainsKey(3))
       myDict[outerKey][3] = 4; //this will succeed because we aren't enumerating the inner dict
}

Consider carefully whether this is the best data storage container for your needs; it's slightly convoluted to have a dictionary of dictionaries and you might do better making a compound key out of your uints and using a single dictionary or picking on another data storage container all together

Upvotes: 1

Michał Turczyn
Michał Turczyn

Reputation: 37367

The way you using foreach in very iteration you get KeyValuePair, which can't be iterated over, as error states.

So you need the value inside outer foreach, which would be the Dictionary you can iterate over, something like this:

foreach(var item in myDict)
{
    foreach(var rt in item.Value)
    {
        ...
    }
}

Also, you could use myDict.SelectMany(kvp => kvp.Value).ToArray(); which would return array with all key and value pairs from all dictionaries, then you can iterate over all of them at once (without nesting loops).

Upvotes: 4

Related Questions