A dictionary object that uses ranges of values for keys

14,571

Solution 1

A dictionary is not the appropriate data structure for the operations you are describing.

If the intervals are required to never overlap then you can just build a sorted list of intervals and binary search it.

If the intervals can overlap then you have a more difficult problem to solve. To solve that problem efficiently you'll want to build an interval tree:

http://en.wikipedia.org/wiki/Interval_tree

This is a well-known data structure. See "Introduction To Algorithms" or any other decent undergraduate text on data structures.

Solution 2

This is only going to work when the intervals don't overlap. And your main problem seems to be converting from a single (key) value to an interval.

I would write a wrapper around SortedList. The SortedList.Keys.IndexOf() would find you an index that can be used to verify if the interval is valid and then use it.

Solution 3

This isn't exactly what you want but I think it may be the closest you can expect.

You can of course do better than this (Was I drinking earlier?). But you have to admit it is nice and simple.

var map = new Dictionary<Func<double, bool>, double>()
{
    { d => d >= 0.0 && d <= 10.0, 9.0 }
};

var key = map.Keys.Single(test => test(1.0))
var value = map[key];

Solution 4

I have solved a similar problem by ensuring that the collection is contiguous where the intervals never overlap and never have gaps between them. Each interval is defined as a lower boundary and any value lies in that interval if it is equal to or greater than that boundary and less than the lower boundary of the next interval. Anything below the lowest boundary is a special case bin.

This simplifies the problem somewhat. We also then optimized key searches by implementing a binary chop. I can't share the code, unfortunately.

Share:
14,571
Jeffrey Cameron
Author by

Jeffrey Cameron

I am a multi-faceted leader and developer with a wide range of skills and interests. I have developed applications in C, SAS, C# and Java. I have hobbied in F#, Scala, Kotlin and Python. I led one of the first Kanban implementations in the Canadian Federal Government (Statistics Canada). I pioneered and led the adoption of Behavior Driven Development (or Specification by Example) at Statistics Canada. Lately, I have been working as a software development manager for Saba Software (formerly Halogen Software) leading platform and product teams to successfully deliver features for our products.

Updated on June 25, 2022

Comments

  • Jeffrey Cameron
    Jeffrey Cameron almost 2 years

    I have need of a sort of specialized dictionary. My use case is this: The user wants to specify ranges of values (the range could be a single point as well) and assign a value to a particular range. We then want to perform a lookup using a single value as a key. If this single value occurs within one of the ranges then we will return the value associated to the range.

    For example:

    // represents the keyed value
    struct Interval
    {
        public int Min;
        public int Max;
    }
    
    // some code elsewhere in the program
    var dictionary = new Dictionary<Interval, double>();
    dictionary.Add(new Interval { Min = 0, Max = 10 }, 9.0);
    var result = dictionary[1];
    if (result == 9.0) JumpForJoy();
    

    This is obviously just some code to illustrate what I'm looking for. Does anyone know of an algorithm to implement such a thing? If so could they point me towards it, please?

    I have already tried implementing a custom IEqualityComparer object and overloading Equals() and GetHashCode() on Interval but to no avail so far. It may be that I'm doing something wrong though.