Loop in Dictionary - c#

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

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.

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.

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.

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.

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

Related

How can I loop over all items in a dictionary which satisfy some condition? C#

I'm currently working on a project where I have to loop over a dictionary. I only want to loop over the keys in this dictionary which contain a substring of a. So for a dictionary (key, value) I only want to loop through the pairs in this dictionary for which the key contains A.
How would I do this?
How would I do this?
Dictionaries only offer O(1) (fast) access when checking for equality. There's not a way to "select" keys that contain a value without looping:
foreach(var entry in myDictionary)
{
if(entry.Key.Contains("A"))
// do something with entry.Value
}
You could use the Where method from Linq but it doesn't offer any performance improvement (it still loops internally):
foreach(var entry in myDictionary.Where(e => e.Key.Contains("A"))
{
// do something with entry.Value
}
Lots of ways. Here is one example (not tested).
var keys = dictionary.Keys.Where(k => k.Contains(a));
foreach (var matchingKey in keys)
{
var value = dictionary[matchingKey];
// Do something
}

Find missing element in in dictionary from relative hashset [duplicate]

This question already has answers here:
How can I check if a HashSet contains an item using the hash of the item?
(2 answers)
Closed 8 years ago.
I'm beginner in C#.. I'm in a situation where I have a dictionary of
var enteries = new Dictionary<int, Entry>();
and I'm iterating over it by
foreach (KeyValuePair<int, Entry> entry in enteries)
I have a hashset<int> that has all keys like 1,2,3. Sometimes the dictionary is missing a key, how would I know if the current key that I'm iterating of over in the dictionary is missing from the hashset ?
Basically I'm trying to write CVS file and I need to know if if there is key is missing, so that I can write some empty row for that id.
I also want things to be sorted..
Looks like there is a misunderstanding:
Suppose enteries have keys, 238, 260
hashset has 238,260,250
How would I relate when I iterate over each key,pair in the dictionary, that there is a missing element, which is 250, and I should output something for example.
The simplest code won't be the most efficient, but will work; union the set of keys together and then iterate that:
foreach (int key in enteries.Keys.Union(yourHashSet)) {
Entry entry;
if (enteries.TryGetValue(key, out entry)) {
// The key is in the dictionary; the entry variable contains the value.
} else {
// The key is not in the dictionary.
}
}
If you want to sort the keys, just apply this operation after the union:
foreach (int key in enteries.Keys.Union(yourHashSet).OrderBy(i => i)) {
how would I know if the current key that I'm iterating of over in the
dictionary is missing from the hashset ?
Assuming you've got a HashSet<int> hashSet instance you could use the Contains method to determine whether an integer value is contained within this hashset and act accordingly:
HashSet<int> hashSet = ...
foreach (KeyValuePair<int, Entry> entry in enteries)
{
if (hashSet.Contains(entry.Key))
{
// The current key is contained within the hashSet
}
else
{
// The current key is not contained within the hashSet
}
}
Change your point of view.
As I understand in your HashSet is every needed Key. So iterate through the HashSet and find the key to every HashSet-Entry in the Dictionary.

What type is the best for loose numerically-indexed lists in C#?

What I need is something like an array but letting me to assign an element to whatever an index at any time and check if there is already a value assigned to particular index approximately like
MyArray<string> a = new MyArray<string>();
a[10] = "ten";
bool isTheFifthElementDefined = a[5] != null; // false
Perhaps Dictionary<int, string> with its ContainsKey method could do, but isn't there a more appropriate data structure if I want an ordered collection with numeric keys only?
I am also going to need to iterate through the defined elements (with foreach or linq preferably) accessing both the value and the key of current element.
As you mentioned Dictionary seems more appropriate for this.But you can do it with generic lists,for example, when you are creating your list you can specify an element count,and you can give a default temporary value for all your elements.
List<string> myList = new List<string>(Enumerable.Repeat("",5000));
myList[2300] = "bla bla bla..";
For int:
List<int> myList = new List<int>(Enumerable.Repeat(0,5000));
For custom type:
List<MyClass> myList = new List<MyClass>(Enumerable.Repeat(new MyClass(), 100));
Ofcourse It is not the best solution...
Note: Also you can use SortedList instead of Dictionary if you want an ordered collection by keys:
SortedList<TKey, TValue> : Represents a collection of key/value pairs that are sorted by key based on the associated IComparer implementation.
If you need key/value pairs you cannot use a list, you'll need a Dictionary.
The implementation is pretty snappy so don't be too afraid about performance (as long as you don't put too much values in it).
You can iterate over it with
foreach(KeyValuePair<int, string> kvp in dict)
{
}
If you need to order it you can use a list:
List<int> ordered = new List(dict.Keys);
ordered.Sort();
foreach(int key in ordered)
{
}

Dictionary<string, List<int>> copy to another Dictionary

I have a problem with copying the values ​​of the numbers into another dictionary.
Everything goes well, but as soon as I add values ​​from a List to another dictionary if the key already exists. I do not understand how it is possible that the same values ​​are added to the dictionary as well as going through.
foreach (KeyValuePair<string, List<int>> record in dictonaryUnStem)
{
arrayWord = record.Key.ToCharArray();
st.add(arrayWord);
stemWord = st.stem();
if (!dictonaryStem.ContainsKey(stemWord))
{
dictonaryStem.Add(stemWord, record.Value);
}
else
{
foreach (int i in record.Value)
{
dictonaryStem[stemWord].Add(i);
}
}
}
When you add to another dictionary from the given key integers. We join me on the record, too integers dictionaryUnStem. It is a complete illogical.
stemWord = st.stem()
gives me root word which is the key word in the first dictionary. In the list are stored position of that words in the text.
The problem is here:
dictonaryStem.Add(stemWord, record.Value);
You are setting the dictionary value to the reference of the original list (List<T> is a reference type) - hence when you add an item to that list, it also shows up in the dictionary - both reference the same list.
Instead you can just force creation of a new list for your dictionary:
dictonaryStem.Add(stemWord, record.Value.ToList());

The best way to use dictionary items as we use the advantages of List

I want to get use of dictionary items like I do in List generic class,
e.g;
foreach(item in ItemList)
{
item.BlaBla;
}
But in dictionary there s no chance, like e method above...
Dictionary<string, HtmlInputImage> smartPenImageDictionary;
I mean I got to know the key item for the dictionary item.. but what I want, I want to travel from beginning of the list till the end..
I am not absolutely sure what you want to achieve but here are the common things you can do with a dictionary.
IDictionary<Int32, String> dictionary = new Dictionary<Int32, String>();
// Iterate over all key value pairs.
foreach (KeyValuePair<Int32, String> keyValuePair in dictionary)
{
Int32 key = keyValuePair.Key;
String value = keyValuePair.Value;
}
// Iterate over all keys.
foreach (Int32 key in dictionary.Keys)
{
// Get the value by key.
String value = dictionary[key];
}
// Iterate over all values.
foreach (String value in dictionary.Values)
{
}
Iterating over a dictionary results in KeyValuePair<>s. Simply access the Key and Value members of the appropriate variable.
Something like this:
foreach (KeyValuePair<string, HtmlInputImage> kvp in smartPenImageDictionary)
{
Console.WriteLine("Value " + kvp.Value);
}
A dictionary doesn't have a "beginning" and "end" - it's unordered.
However, you can iterate over the keys or the values:
foreach (string key in smartPenImageDictionary.Keys)
{
...
}
foreach (HtmlInputImage image in smartPenImageDictionary.Values)
{
...
}
or key/value pairs:
foreach (KeyValuePair<string, HtmlInputImage> pair in smartPenImageDictionary)
{
string key = pair.Key;
HtmlInputImage image = pair.Value;
...
}
(Or course var makes the last case rather nicer.)
I assume you want them in order, the same way an IList<T> provides. As far as I know there is no order guaranteed for a Dictionary<Tkey,TValue>, so you'll need to
mydictionary.ToList();
However as you add and remove items, or even call this again it may change. One solution is to write your own Collection that has a custom indexer you can use.

Categories