在python中是否有一个库实现了RangeDict?

时间:2015-05-15 08:18:22

标签: python

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

2 个答案:

答案 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