I have an application that use managed dlls. One of those dlls return a generic dictionary:
Dictionary<string, int> MyDictionary;
The dictionary contains keys with upper and lower case.
On another side I am getting a list of potential keys (string) however I cannot guarantee the case. I am trying to get the value in the dictionary using the keys. But of course the following will fail since I have a case mismatch:
bool Success = MyDictionary.TryGetValue( MyIndex, out TheValue );
I was hoping the TryGetValue would have an ignore case flag like mentioned in the MSDN doc, but it seems this is not valid for generic dictionaries.
Is there a way to get the value of that dictionary ignoring the key case? Is there a better workaround than creating a new copy of the dictionary with the proper StringComparer.OrdinalIgnoreCase parameter?
In the Dictionary constructor you can specify how keys are compared. For string keys, the default is a case sensitive comparison. To make it case insensitive, you can pass in StringComparer. InvariantCultureIgnoreCase.
The default constructor of C# Dictionary class constructs a Dictionary object, in which the keys are case sensitive. So when you insert data pairs <Key, Value> and <key, Value>, they are regarded as two different items.
Dictionary Keys Are Case-Sensitive : Dictionary Key « Dictionary « Python.
I want to know whether a particular key is present in a HashMap, so i am using containsKey(key) method. But it is case sensitive ie it does not returns true if there is a key with Name and i am searching for name.
There's no way to specify a StringComparer
at the point where you try to get a value. If you think about it, "foo".GetHashCode()
and "FOO".GetHashCode()
are totally different so there's no reasonable way you could implement a case-insensitive get on a case-sensitive hash map.
You can, however, create a case-insensitive dictionary in the first place using:-
var comparer = StringComparer.OrdinalIgnoreCase; var caseInsensitiveDictionary = new Dictionary<string, int>(comparer);
Or create a new case-insensitive dictionary with the contents of an existing case-sensitive dictionary (if you're sure there are no case collisions):-
var oldDictionary = ...; var comparer = StringComparer.OrdinalIgnoreCase; var newDictionary = new Dictionary<string, int>(oldDictionary, comparer);
This new dictionary then uses the GetHashCode()
implementation on StringComparer.OrdinalIgnoreCase
so comparer.GetHashCode("foo")
and comparer.GetHashcode("FOO")
give you the same value.
Alternately, if there are only a few elements in the dictionary, and/or you only need to lookup once or twice, you can treat the original dictionary as an IEnumerable<KeyValuePair<TKey, TValue>>
and just iterate over it:-
var myKey = ...; var myDictionary = ...; var comparer = StringComparer.OrdinalIgnoreCase; var value = myDictionary.FirstOrDefault(x => String.Equals(x.Key, myKey, comparer)).Value;
Or if you prefer, without the LINQ:-
var myKey = ...; var myDictionary = ...; var comparer = StringComparer.OrdinalIgnoreCase; int? value; foreach (var element in myDictionary) { if (String.Equals(element.Key, myKey, comparer)) { value = element.Value; break; } }
This saves you the cost of creating a new data structure, but in return the cost of a lookup is O(n) instead of O(1).
For you LINQers out there that never use a regular dictionary constructor
myCollection.ToDictionary(x => x.PartNumber, x => x.PartDescription, StringComparer.OrdinalIgnoreCase)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With