Loop through System.Collections.Generic.Dictionary via for statement - c#

I have a quick question. Is there way to easy loop through System.Collections.Generic.Dictionary via for statement in C#?
Thanks in advance.

You can use foreach:
Dictionary<string,string> dictionary = new Dictionary<string,string>();
// ...
foreach (KeyValuePair<string,string> kv in dictionary)
{
string key = kv.Key;
string value = kv.Value;
}

Not in a reasonable way, no. You could use the Linq extension ElementAt:
for (int i = 0; i < dictionary.Keys.Count; i++)
{
Console.WriteLine(dictionary.ElementAt(i).Value);
}
...but I really don't see the point. Just use the regular foreach approach. If you for some reason need to keep track of an index while iterating, you can do that "on the side":
int index = 0;
foreach (var item in dictionary)
{
Console.WriteLine(string.Format("[{0}] - {1}", index, item.Value));
// increment the index
index++;
}

There are several ways.
Looping through the keys:
foreach(var key in myDictionary.Keys)
looping through values:
foreach(var value in myDic.Values)
looping through pairs:
foreach(KeyValuePair<K, V> p in myDic)
{
var key = p.Key;
var value = p.Value
}

No, for is mostly for collections with indices.
You can foreach over it easily, however.

If you are using Net 3.5 or later then you can use LINQ and a predecate to locate a specific Value or Values.
Dictionaries do not necessarily store their KeyValue pairs in order (either by entry order nor Key order).

Philippe's got it for foreach, though I usually simplify it to:
foreach (var pair in dictionary)
{
var key = pair.Key;
var value = pair.Value;
}
There's no way to loop through this collection of key-value pairs using a for loop because they aren't stored in order. You can loop through the keys or the values as collections though.

It can ofc be done, but it is a bit silly IMO
Dictionary<string,string> dictionary = new Dictionary<string, string>();
Dictionary<string, string>.Enumerator enumerator = dictionary.GetEnumerator();
for (int i = 0; i < attributeValues.Count;i++ )
{
KeyValuePair<string, string> current = enumerator.Current;
//do something usefull
enumerator.MoveNext();
}
the only thing gained by this is a (fairly useless) index, and if that is the actual goal, you are better served by something like this:
int currentIndex = 0;
foreach (KeyValuePair<string, string> keyValuePair in dictionary)
{
//do something usefull
currentIndex++;
}

If it does not have to be a "for"-loop, maybe using the Dictionary.GetEnumerator Method with a "while"-loop is an option - it is pretty easy as well IMHO:
var enumerator = d.GetEnumerator();
while (enumerator.MoveNext())
{
var pair = enumerator.Current;
b += pair.Value;
}
enumerator.Dispose();
code-snippet from C# Dictionary GetEnumerator

You can loop over the keys
for(int i = 0; i < myDictionary.Keys.Length; ++i)
myDictionary.Keys[i] ...
or the values
for(int i = 0; i < myDictionary.Values.Length; ++i)
myDictionary.Values[i] ...
Or both as Philippe shows

Related

Is there any way to edit the Values of a Dictionary during iteration?

I want to change all the values that fulfill a certain criterium in a C# dictionary.
Simply editing the values like this
foreach (var kv in dictionary)
{
kv.Value += 1;
}
does not work because the KeyValuePair of the foreach loop is read only.
However, editing the entries directly like this:
foreach (var kv in dictionary)
{
dictionary[kv.Key] = kv.Value + 1;
}
also doesn't work, because it modifies the collection and breaks the iterator.
At this point, the only remaining solution I can think of is storing all keys of the dictionary in a list, and then using that to edit the values during a second loop, however, that seems like a pretty inelegant solution to me.
Is there any better alternative?
You could create an array (or a List with .ToList()) from the .Keys in the foreach, something like this:
foreach (string key in dictionary.Keys.ToArray())
{
dictionary[key] += 1;
}
You can use ToDictionary to create new Dictionary and change the origin in the loop, like :
foreach (var kv in dictionary.ToDictionary(k=>k.Key,v=>v.Value))
{
dictionary[kv.Key] = kv.Value + 1;
}
I hope you find this helpful.

the given key was not present in the dictionary error debugging

When I debug the following code, it always throws the following exception:
The given key was not present in the dictionary.
I need help figuring it out.
string current;
Dictionary<string, List<int>> map = new Dictionary<string, List<int>>();
for (int i = 0; i < y; i++){
current = lines[i].material.Text + "," + lines[i].profilid.Text;
if (map[current] == null){
map[current] = new List<int>();
}
map[current].Add(i);
material_profile.Add(current);
}
foreach (KeyValuePair<string, List<int>> entry in map){
List<int> lenghts = new List<int>();
// do something with entry.Value or entry.Key
for (int i = 0; i < entry.Value.Count(); i++){
int stueckzahl = int.Parse(lines[entry.Value[i]].stueck.Text);
int laenge = int.Parse(lines[entry.Value[i]].länge.Text);
for (int j = 0; j < stueckzahl; j++){
lenghts.Add(laenge);
}
}
}
The code map[current] == null attempts to fetch the value from map[current], and this will throw an error if there is no item.
If you wish to attempt to fetch an item which may not be present, you need to use the TryGetValue method.
This will work:
List<int> list;
if (!(map.TryGetValue(current, out list)))
{
list= new List<int>();
map.Add(current, list);
}
list.Add(i);
As Andrew Shepherd pointed out, you can't look up a value that does not exist in a Dictionary.
For your test to make sense, you would have to expect map[current] to actually return the value null, but that would require the dictionary to actually contain a key-value pair where the key is the same value as current, and the value is null. In your case, that key does not exist at all.
The simplest solution to your problem may be to replace this line...
if (map[current] == null)
...with the following:
if (!map.ContainsKey(current))
That will search for the key without throwing an exception if it is not found.
PS: You could also use map.Add(current, new List<int>); on the proceeding line instead of the []-syntax - I personally think using .Add(..) makes the code a little simpler, but that may be a matter of preference.

Modifying the contents of a Dictionary in foreach loop

I am trying to update the contents of a C# Dictionary in a foreach loop, when a certain condition is met.
foreach (KeyValuePair<int, Corpus_22_04_2014_StreetTable_Row> entry in id_StreetNameDictionary)
{
if(something_happens())
{
Corpus_22_04_2014_StreetTable_Row r = entry.Value;
//Modify r
id_StreetNameDictionary[entry.Key] = r;
}
}
This throws an InvalidOperationException stating that "Collection was modified; enumeration operation may not execute.". It seems that we are not allowed to modify the contents of a Dictionary in foreach loop.
What can be a possible workaround to that?
You can simply use ToList on the dictionary to copy each key-value pair into a list. Then iterate over that list instead of Dictionary:
foreach (var entry in id_StreetNameDictionary.ToList())
{
if(something_happens())
{
Corpus_22_04_2014_StreetTable_Row r = entry.Value;
//Modify r
id_StreetNameDictionary[entry.Key] = r;
}
}
Create a list of all the keys and iterate that. For example:
foreach (var key in id_StreetNameDictionary.Keys.ToList())
{
if(something_happens())
{
var r = id_StreetNameDictionary[key];
//Modify r
id_StreetNameDictionary[key] = r;
}
}
This will be somewhat more memory efficient than creating a list of KeyValuePair structures from the dictionary.
Since it appears you really want to modify the row and not necessarily the Dictionary, then do so directly:
foreach (var entry in id_StreetNameDictionary)
{
if (something_happens())
{
((Corpus_22_04_2014_StreetTable_Row)entry.Value)["FieldToChange"] = newValue;
//...repeat for each field to change...you will be altering the row directly, no need to reassign it
}
}
Well I use the following workaround. Not very efficient maybe, but it does the work.
I declare three dictionaries:
Dictionary<int, Corpus_22_04_2014_StreetTable_Row> id_StreetNameDictionary = new Dictionary<int, Corpus_22_04_2014_StreetTable_Row>();
Dictionary<int, Corpus_22_04_2014_StreetTable_Row> tempDictionary = new Dictionary<int, Corpus_22_04_2014_StreetTable_Row>();
Dictionary<int, Corpus_22_04_2014_StreetTable_Row> swapBuffer;
I completely dump the old dictionary, with all modified and unmodified key/value pairs, into the tempDictionary. Then I swap both dictionaries and clear the unused one:
foreach (var entry in id_StreetNameDictionary)
{
Corpus_22_04_2014_StreetTable_Row row = id_StreetNameDictionary[entry.Key];
if (something_happens())
{
//Modify row
}
tempDictionary.Add(row.id, row);
}
swapBuffer = tempDictionary;
tempDictionary = id_StreetNameDictionary;
id_StreetNameDictionary = swapBuffer;
tempDictionary.Clear();

Getting rid of duplicates inside List<> contained within a dictionary

I have the following dictionary.
Dictionary<string, List<string>> dictSubjects = new Dictionary<string, List<string>>();
and I am trying to get rid of potential duplicates residing within each list instace of the respective dictionary entry.
This is what I have tried but get and error along the lines of the list being read only
foreach (var kvp in dictSubjects)
{
lstSubjectsNoDupes.Clear();
for (int i = kvp.Value.Count - 1; i >= 0; i--)
{
if(lstSubjectsNoDupes.Contains(kvp.Value[i]))
{
lstSubjectsNoDupes.Add(kvp.Value[i]);
}
}
kvp.Value = lstSubjectsNoDupes;
}
How can I effectively get rid of potential duplicates within each list of my Dictionary?
The simplest way if you don't care too much about efficiency would be:
dictSubjects = dictSubjects.ToDictionary(pair => pair.Key,
pair => pair.Value.Distinct().ToList());
Alternatively, to update the existing dictionary:
foreach (var key in dictSubjects.Keys.ToList())
{
dictSubjects[key] = dictSubjects[key].Distinct().ToList();
}
Note the use of ToList here to avoid iterating over a view of a collection which is being modified. Without this, InvalidOperationException is thrown.
What about
foreach (var kvp in dictSubjects.ToList())
dictSubjects[kvp.Key] = kvp.Value.Distinct().ToList();

how to change Dictionary's value when enumerate it?

how to change Dictionary's value when enumerate it?
the following code doesn't work, because we can not change dictionary's value when enumerating it. Is there any way to get around it? Or NO WAY? Thanks
foreach (KeyValuePair<string, int> kvp in mydictionary)
{
if (otherdictionary.ContainsKey(kvp.Key))
{
mydictionary[kvp.Key] = otherdictionary[kvp.Key];
}
else
{
otherdictionary[kvp.Key] = mydictionary[kvp.Key];
}
}
The simplest way would be to take a copy first. As you only want the key value pairs, you might as well put them in a list rather than building a new dictionary though. Also, you can avoid doing quite as many lookups using TryGetValue.
var copy = myDictionary.ToList();
foreach (KeyValuePair<string, int> kvp in copy)
{
int otherValue;
if (otherdictionary.TryGetValue(kvp.Key, out otherValue))
{
mydictionary[kvp.Key] = otherValue;
}
else
{
otherdictionary[kvp.Key] = kvp.Value;
}
}
Make a copy of the values you need to enumerate over before you enumerate over them, then you can change the original source.
Since you don't actually use the value, you can change the code to this:
foreach (string key in mydictionary.Keys.ToArray())
if (otherdictionary.ContainsKey(key))
mydictionary[key] = otherdictionary[key];
else
otherdictionary[key] = mydictionary[key];
Note the use of .ToArray() there to make a temporary array copy of the key collection. This is now separate from the source dictionary, so you can change the dictionary all you want.
another option, copy the keys collection to an array and use it in for each loop -
string[] arr1 = new string[mydictionary.Count];
mydictionary.Keys.CopyTo(arr1,0);
foreach (string j in arr1)
{
if (otherdictionary.ContainsKey(j))
{
mydictionary[j] = otherdictionary[j];
}
else
{
otherdictionary[j] = mydictionary[j];
}
}

Categories

Resources