在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)]
此方法的效率如下所示:
此外,您的
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。现在这是正确的方式做它!我很高兴有人强调。这是低效的。