How to Find Item in Dictionary Collection?
C#GenericsDictionaryC# Problem Overview
I have declared and populated the following collection.
protected static Dictionary<string, string> _tags;
Now I want to look locate a particular entry in the collection. I tried the following.
thisTag = _tags.FirstOrDefault(t => t.Key == tag);
if (thisTag != default(KeyValuePair<string, string>))
...
And I get the error:
> Operator '!=' cannot be applied to operands of type 'System.Collections.Generic.KeyValuePair
Initially I attempted to compare the result to null
, and I guess that's not supported with struct
s.
I would've thought that finding an item within a collection is a very trivial task. So how the heck to I determine if the item I'm looking for was found?
(Note: I'm using Dictionary
because I want fast lookups. I know I can use Contains()
to determine if the item is there. But that means a total of two lookups, which sort of defeats the purpose of having a fast lookup. I'll happily using a different collection if it can quickly lookup an item and I have a way to determine if it was successful.)
C# Solutions
Solution 1 - C#
thisTag = _tags.FirstOrDefault(t => t.Key == tag);
is an inefficient and a little bit strange way to find something by key in a dictionary. Looking things up for a Key is the basic function of a Dictionary.
The basic solution would be:
if (_tags.Containskey(tag)) { string myValue = _tags[tag]; ... }
But that requires 2 lookups.
TryGetValue(key, out value)
is more concise and efficient, it only does 1 lookup. And that answers the last part of your question, the best way to do a lookup is:
string myValue;
if (_tags.TryGetValue(tag, out myValue)) { /* use myValue */ }
VS 2017 update, for C# 7 and beyond we can declare the result variable inline:
if (_tags.TryGetValue(tag, out string myValue))
{
// use myValue;
}
// use myValue, still in scope, null if not found
Solution 2 - C#
Sometimes you still need to use FirstOrDefault if you have to do different tests. If the Key component of your dictionnary is nullable, you can do this:
thisTag = _tags.FirstOrDefault(t => t.Key.SubString(1,1) == 'a');
if(thisTag.Key != null) { ... }
Using FirstOrDefault, the returned KeyValuePair's key and value will both be null if no match is found.
Solution 3 - C#
It's possible to find the element in Dictionary collection by using ContainsKey or TryGetValue as follows:
class Program
{
protected static Dictionary<string, string> _tags = new Dictionary<string,string>();
static void Main(string[] args)
{
string strValue;
_tags.Add("101", "C#");
_tags.Add("102", "ASP.NET");
if (_tags.ContainsKey("101"))
{
strValue = _tags["101"];
Console.WriteLine(strValue);
}
if (_tags.TryGetValue("101", out strValue))
{
Console.WriteLine(strValue);
}
}
}
Solution 4 - C#
Of course, if you want to make sure it's in there otherwise fail then this works:
thisTag = _tags[key];
NOTE: This will fail if the key,value pair does not exists but sometimes that is exactly what you want. This way you can catch it and do something about the error. I would only do this if I am certain that the key,value pair is or should be in the dictionary and if not I want it to know about it via the throw.