Peter Petrov’s Weblog

var me = from practice in programming where practice.IsBestPractice && practice.UseLambda select practice.OptimalPerformance;

Usuful methods – 10 of N – Dictionary with unique values July 4, 2008

The .NET Dictionary<TKey, TValue> is a great class.

MSDN:

The Dictionary<(Of <(TKey, TValue>)>) generic class provides a mapping from a set of keys to a set of values. Each addition to the dictionary consists of a value and its associated key. Retrieving a value by using its key is very fast, close to O(1), because the Dictionary<(Of <(TKey, TValue>)>) class is implemented as a hash table

I’m using this class very often. I’m not going to explain when to use a dictionary, an array, a sorted array or a tree or any other data structures – there is a lot of articles on this subject on the net. Instead I’ll extend the class and I’ll constraint the set of values to be unique which will give us a one-to-one mapping.It’s a very simple thing to do.

public class UniqueValuesDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
    public new void Add(TKey key, TValue value)
    {
        if (this.Values.Count > 0)
        {
            bool hasDuplicates = this.Values.Contains(value);
            if (hasDuplicates)
            {
                throw new ArgumentException("An element with the same value already exists.");
            }
        }
        base.Add(key, value);
    }
}

And here’s an example which demonstrates how this class will help us find errors

            var lookup = new Dictionary<int, string>();
            lookup.Add(1, "One");
            lookup.Add(2, "One");   // No exception as expected

            var uniqueLookup = new UniqueValuesDictionary<int, string>();
            uniqueLookup.Add(1, "One");
            uniqueLookup.Add(2, "One"); // Here we'll get an exception
Advertisements
 

Usuful methods – 9 of N – Count string occurences July 2, 2008

One more extension method(hopefully useful) on String.  If we want to count how many times a string contains another string this method will help us.

    public static int CountOccurences(this string original, string value)
    {
        return original.CountOccurences(value, StringComparison.CurrentCulture);
    }

    public static int CountOccurences(this string original, string value, StringComparison comparisionType)
    {
        return GenericCountOccurences(original, value, comparisionType, value.Length);
    }

    public static int CountOverlapOccurences(this string original, string value)
    {
        return GenericCountOccurences(original, value, StringComparison.CurrentCulture, 1);
    }

    public static int CountOverlapOccurences(this string original, string value, StringComparison comparisionType)
    {
        return GenericCountOccurences(original, value, comparisionType, 1);
    }

    private static int GenericCountOccurences(string original, string value, StringComparison comparisionType, int step)
    {
        int occurences = 0;

        if (!string.IsNullOrEmpty(original))
        {
            int foundIndex = original.IndexOf(value, 0, comparisionType);
            while (foundIndex >= 0)
            {
                occurences++;
                foundIndex = original.IndexOf(value, foundIndex + step, comparisionType);
            }
        }

        return occurences;
    }

We have two versions – simple and overlapping.
When we use the simple version like this

            var input = "aaaa";
            var count = input.CountOccurences("aa");

we’ll have count = 2.
When we use the overlapping one on the same input

            var input = "aaaa";
            var count = input.CountOverlapOccurences("aa");

we’ll have count = 3.

That’s because the search of the next occurrence begins right after the start of the match and in the other version the search begins after the end of the previous match.

Note: I’m sure my colleague and friend Vlado will appreciate this 😉