RangeMap
中有一个guava
实现,可用于将范围映射到对象。
python中是否有类似的库?我还没有通过谷歌搜索找到一个。
为了更清楚地提出问题,RangeDict
我指的是一个集合支持用法,如:
rd = RangeDict()
rd[[1,2]] = 'A'
rd[[11,22]] = 'B'
print rd[1] # A
print rd[12] # B
print 23 in rd # False
print 18 in rd # True
EIDT:
由于似乎没有这样的模块,我写了一个here,您可以通过pip install rangedict
安装它并像这样使用它:
>>> from rangedict import RangeDict
>>> rd = RangeDict()
>>> rd[(1, 2)] = 1
>>> rd[(3, 3)] = 3
>>> rd[(5, 7)] = 5
>>> print rd[6]
5
>>> 3 in rd
True
>>> del rd[(3, 3)]
>>> 3 in rd
False
答案 0 :(得分:3)
我很快想出了这个满足你的四个断言。
import collections
class RangeDict(collections.MutableMapping):
def __init__(self, *args, **kwargs):
self.store = dict()
self.update(dict(*args, **kwargs))
def __getitem__(self, key):
return self.store[self.transform_key(key)]
def __setitem__(self, key, value):
self.store[key] = value
# two possible behaviours
def __delitem__(self, key):
del self.store[self.transform_key(key)]
# del self.store[key]
def __iter__(self):
return iter(self.store)
def __len__(self):
return len(self.store)
def transform_key(self, key):
for k in self.iterkeys():
if k[0] <= key <= k[1]:
return k
return key # this behaviour would need to be better defined
然而,您需要使用元组作为键(不可变),而不是列表(可变)。
rd = RangeDict()
rd[(1,2)] = 'A'
rd[(11,22)] = 'B'
答案 1 :(得分:0)
快速简便:
class RangeDict():
def __init__(self):
self._dict = {}
def __getitem__(self, key):
for k, v in self._dict.items():
if k[0] <= key < k[1]:
return v
raise KeyError("Key not found!")
def __setitem__(self, key, value):
if len(key) == 2:
if key[0] < key[1]:
self._dict.__setitem__((key[0], key[1]), value)
def __contains__(self, key):
try:
return bool(self.__getitem__(key))
except KeyError:
return False
rd = RangeDict()
rd[[1, 2]] = 'A'
rd[[11, 22]] = 'B'
print(rd[1]) # A
print(rd[18]) # B
print(23 in rd) # False
print(18 in rd) # True