代码之家  ›  专栏  ›  技术社区  ›  Jeffrey Cameron

使用键值范围的Dictionary对象

  •  22
  • Jeffrey Cameron  · 技术社区  · 16 年前

    我需要一本专门的字典。我的用例是这样的:用户想要指定值的范围(范围也可以是一个单点)并为特定的范围分配一个值。然后我们希望使用单个值作为键执行查找。如果此单个值出现在某个范围内,那么我们将返回与该范围关联的值。

    例如:

    // 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();
    

    这显然只是一些代码来说明我在寻找什么。有人知道实现这种事情的算法吗?如果可以的话,他们能指给我看吗?

    我已经尝试实现一个自定义的IEqualityComparer对象,并在Interval上重载equals()和getHashCode(),但到目前为止没有任何效果。可能是我做错了什么。

    7 回复  |  直到 16 年前
        1
  •  26
  •   Eric Lippert    16 年前

    字典不是您描述的操作的适当数据结构。

    如果要求间隔永远不重叠,那么您可以构建一个间隔的排序列表并对其进行二进制搜索。

    如果间隔可以重叠,那么就有一个更难解决的问题。为了有效地解决这个问题,您需要构建一个间隔树:

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

    这是一个众所周知的数据结构。请参阅“算法简介”或有关数据结构的任何其他体面的本科文本。

        2
  •  6
  •   Henk Holterman    16 年前

    只有当间隔不重叠时,这才有效。您的主要问题似乎是从一个(键)值转换为一个间隔。

    我会在排序列表周围写一个包装。sortedList.keys.indexof()将为您找到一个索引,该索引可用于验证间隔是否有效,然后使用它。

        3
  •  3
  •   ChaosPandion    16 年前

    这不完全是你想要的,但我认为这可能是你能预料到的最接近的。

    你当然可以做得比这更好(我以前喝酒吗?)但是你必须承认这是一个简单而美好的过程。

    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];
    
        4
  •  1
  •   Jeff Yates    16 年前

    我通过确保集合是连续的来解决类似的问题,其中间隔永远不会重叠,并且它们之间也不会有间隙。每个间隔都定义为下一个边界,如果该边界等于或大于该边界且小于下一个间隔的下边界,则任何值都位于该间隔中。任何低于最低边界的东西都是一个特殊的箱子。

    这在一定程度上简化了问题。然后,我们还通过实现二进制CHOP来优化密钥搜索。很遗憾,我不能共享代码。

        5
  •  0
  •   Oliver    16 年前

    我会做一个小的间歇课,就像这样:

    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);
            }
        }
    }
    

    所以你仍然可以在字典中进行正常的查找。也许你在打电话之前也应该做些检查 Add() 或者,如果字典中已有任何值,则实现某种回滚。

        6
  •  0
  •   Jonas Elfström    16 年前

    你可以找到一个 Java flavored c在 Open Geospatial Library . 它需要一些小的调整来解决你的问题,它也可以真正地使用一些C语言。

    它是开源的,但我不知道在什么许可下。

        7
  •  -2
  •   t0mm13b    16 年前

    你可以在这里查看PowerCollections codeplex 它有一个集合,可以做你想要的。

    希望这有帮助, 最好的问候, 汤姆。