LP on .NET

December 27, 2011

Case-Invariant Dictionaries

Filed under: .NET,C# — Larry Parker @ 4:26 pm

A few months back I posted about case-invariant string comparisons using the Equals method and the StringComparison enum.  This approach made it a bit more efficient to compare strings without regards to their case since it wasn’t necessary to convert the strings to lower or upper case.

But what if you have a dictionary that is keyed by a string and you wish the lookup to be case insensitive?  The following unit test demonstrates the problem, using a dictionary of city names and temperatures:

private Dictionary<String, Int32> GetDictionary()
{
    Dictionary<String, Int32> dict = new Dictionary<String, Int32>()
    {
        {"New York", 42},
        {"Boston", 35},
        {"Atlanta", 58}
    };
    return dict;
}

[TestMethod]
public void CaseInsensitive_KeyNotFound_Test()
{
    Dictionary<String, Int32> dict = GetDictionary();

    Assert.IsFalse(dict.ContainsKey("new york"));
}

As the test shows, searching the dictionary for the lower-case city of “new york” fails.  If you ask the user to input a city name and they don’t enter it as mixed case, you’re out of luck.

A workaround is to store the cities in the dictionary as upper (or lower) case and always ensure you search by the same case.  But that gets a bit messy.

Fortunately there’s a better way.  One of the Dictionary<TKey, TValue> constructors takes an IEqualityComparer<TKey> that lets you specify how you would like to compare the key of the dictionary.

The following unit test demonstrates this:

[TestMethod]
public void CaseInsensitive_KeyFound_Test()
{
    Dictionary<String, Int32> dict = new Dictionary<String, Int32>(StringComparer.OrdinalIgnoreCase)
    {
        {"New York", 42},
        {"Boston", 35},
        {"Atlanta", 58}
    };

    Assert.IsTrue(dict.ContainsKey("new york"));
}

In this example, we pass in a StringComparer.OrdinalIgnoreCase parameter that tells the dictionary to perform a case-insensitive string comparison.  This lets us find our New York entry regardless of case.  Now we have a better chance of finding the city when the user searches for it.

This is a very handy technique that also works with HashSet<T>.

Hope this helps.

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: