A dictionary object that uses ranges of values for keys

纵饮孤独 提交于 2019-11-26 22:39:13

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.

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.

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];

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.

I would make a little Interval class, which would something like that:

public class Interval
{
    public int Start {get; set;}
    public int End {get; set;}
    public int Step {get; set;}
    public double Value {get; set;}

    public WriteToDictionary(Dictionary<int, double> dict)
    {
        for(int i = Start; i < End; i += Step)
        {
            dict.Add(i, Value);
        }
    }
}

So you still can a normal lookup within your dictionary. Maybe you should also perform some checks before calling Add() or implement some kind of rollback if any value is already within the dictionary.

You can find a Java flavored C# implementation of an interval tree in the Open Geospatial Library. It needs some minor tweaks to solve your problem and it could also really use some C#-ification.

It's Open Source but I don't know under what license.

You could check out the powercollections here found on codeplex that has a collection that can do what you are looking for.

Hope this helps, Best regards, Tom.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!