在Python中使用范围作为字典索引

在Python中使用范围作为字典索引,python,dictionary,Python,Dictionary,是否可以执行以下操作: r = {range(0, 100): 'foo', range(100, 200): 'bar'} print r[42] > 'foo' 所以我想使用数字范围作为字典索引的一部分。为了使事情更加复杂,我还想使用多个索引,如('a',range(0100))。因此,这个概念应该可以理想地扩展到这一点。有什么建议吗 有人问了一个类似的问题,但我感兴趣的是一个全面的实现,而不是这个问题的不同方法。您只能使用不可变的数据类型作为键。所以没有名单 但是您可以使用元组

是否可以执行以下操作:

r = {range(0, 100): 'foo', range(100, 200): 'bar'}

print r[42]

> 'foo'
所以我想使用数字范围作为字典索引的一部分。为了使事情更加复杂,我还想使用多个索引,如
('a',range(0100))
。因此,这个概念应该可以理想地扩展到这一点。有什么建议吗


有人问了一个类似的问题,但我感兴趣的是一个全面的实现,而不是这个问题的不同方法。

您只能使用不可变的数据类型作为键。所以没有名单

但是您可以使用元组来定义上限和下限

r = {(0,100): 'foo', (100,200): 'bar'}
我将通过以下方式获得42的值:

res = ""
for (k1,k2) in r:
    if (k1 < 42 and k2 > 42):
         res = r[(k1,k2)]
print(res)
res=“”
对于r中的(k1,k2):
如果(k1<42和k2>42):
res=r[(k1,k2)]
打印(res)

但我承认,您不需要字典来实现这一点。

如果您使用的是Python 3.x,您可以使用对象作为键,但要检索值,您将执行以下操作:

In [33]: r = {range(0, 100): 'foo', range(100, 200): 'bar'}

In [34]: { r[key] for key in r if 42 in key}
Out[34]: {'foo'}
在Python2.x中无法执行此操作的原因是,版本2.7以后的函数返回一个列表,列表不能用作字典键,因为它们不提供有效的方法。

您可以使用以下方法:

r=dict(zip(range(100),["foo"]*100))
r2=dict(zip(range(100,200),["bar"]*100))
r.update(r2)

作为一种替代方法,如果您试图查找与特定范围相关的值,可以使用内置Python库,如下所示:

import bisect

def boundaries(num, breakpoints=[100, 200], result=['foo', 'bar']):
    i = bisect.bisect(breakpoints, num-1)
    return result[i]

print boundaries(42)
这将显示:

foo

你可以在一行中完成

r = dict(zip(range(200),["foo"]*100+["bar"]*100))
您可以使用以获取所需的词典:

d = dict([(i,'foo') for i in range(0, 100)] + [(i,'bar') for i in range(100, 200)])
print d

如果您有一种简单的方法来计算从一个点开始的范围,例如,如果所有范围的大小都是固定的,您可以使用:

def getIndex(p):
   start = floor(p/100)*100
   return (start, start+100)
然后定义dict:

r = {(0, 100): 'foo', (100, 200): 'bar'}
和访问:

r[getIndex(42)]
此方法的效率如下所示:

  • 您没有为范围内的每个数字保留dict中的项目(这也允许您拥有实值“键”)
  • 你不会通过整个字典来找到一个值,得到一个值是O(1)

  • 此外,您的
    getIndex
    函数可能更复杂,例如,如果您的范围长度不规则,那么
    getIndex
    函数可以对范围边界的排序列表进行二进制搜索并返回范围元组,不再是
    O(1)
    而是
    O(log(n))
    还不错

    范围是固定的吗?假设某个整数的所有值都是
    范围(x*100,(x+1)*100)
    ?@pseudoDust:是的,固定范围我会给出一个答案,给出一个更简单、更有效的解决方案,考虑到问题的缓和,请看一看。它使用:
    类RangeDictionary(TransformedDict):def_uu-keytransform_u(self,key):dk=sorted(self.keys())返回dk[bisect.bisect(dk,key)]
    r=RangeDictionary({100:'foo',200:'bar',250:'xyz});印刷品(r[42]);印刷品(r[142]);打印(r[242])生成
    foo-bar xyz
    。覆盖
    def\uu getitem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu把它添加到我的回答中很好,谢谢。现在确实是时候转向Python 3了。不幸的是,这个项目是在2.7。现在这是正确的方式做它!我很高兴有人强调。这是低效的。