2

如果这很明显,请原谅我,但我对 Python 非常非常陌生。我找到了从字典中获取多个键的方法,但这不是我想要做的。

基本上我正在寻找这样的东西:

my_dict = { "1-10" : "foo",
            "11-20" : "bar",
            # ...
            "91-100" : "baz" }

...但是键实际上不是字符串,并且该给定范围内的任何数字都映射到该值。例如,my_dict[9]应该返回foo,就像my_dict[3]应该一样。我想过使用显式数组,如下所示,但它不起作用:

my_dict = { [1, 2, 3, ..., 10] : "foo",

我不确定这是否是字典的有效用例,或者我是否应该使用其他数据结构。但是 Python 总有一种让我感到惊讶的方式。那么有没有人知道 Python 的魔法来完成这项工作?

4

6 回答 6

3

我必须说我从来没有需要做这样的事情,当然也没有内置的数据结构。(如果你对哈希有任何了解,你就会明白为什么 dict 不能那样工作。)

一种可能性是根本不使用字典,而是有单独的键和值列表,键列表是每个“范围”的开始。所以:

keys = [0, 10, 20, 30]
values = ['foo', 'bar', 'baz', 'quux']

现在您可以使用它bisect来查找相关密钥:

import bisect
pos = bisect.bisect_left(keys, 12)
value = values[pos-1]
于 2013-08-28T14:50:04.773 回答
2

这当然不是常见的情况,我建议使用明显的解决方案:

my_dict = dict((i, "foo") for i in range(1,10))
print my_dict
{1: 'foo', 2: 'foo', 3: 'foo', 4: 'foo', 5: 'foo', 6: 'foo', 7: 'foo', 8: 'foo', 9: 'foo'}

为了添加新元素,您可以使用以下内容更新字典:

my_dict.update(new_elements) 
于 2013-08-28T14:47:08.920 回答
2

这个怎么样:

def fancy_dict(*args):
    'Pass in a list of tuples, which will be key/value pairs'
    ret = {}
    for k,v in args:
        for i in k:
            ret[i] = v
    return ret

那么你也能:

>>> dic = fancy_dict((range(10), 'hello'), (range(100,125), 'bye'))
>>> dic[1]
'hello'
>>> dic[9]
'hello'
>>> dic[100]
'bye'
>>> 

您还可以在其中添加逻辑fancy_dict来检查项目是否为字符串或是否可迭代并相应地创建字典。

于 2013-08-28T14:57:11.280 回答
1

如果你的“范围键”是简单的数学转换,每个潜在的有效键都有唯一的映射,你可以只继承list和覆盖__getitem__and __setitem__,尽管有充分的理由在你的调用代码中使用辅助方法或直接计算(例如index()返回一些特别的东西有意义)。

class RangeList(list):
    def __getitem__(self, index):
        return super(RangeList, self).__getitem__(index / 10 if index else 0)
    def __setitem__(self, index, value):
        super(RangeList, self).__setitem__(index / 10 if index else 0, value)
于 2013-08-28T14:49:21.283 回答
0

我将此作为记录,其他人可能会感兴趣:

如果您制作键元组,它会起作用: my_dict = {(1, 2, 3, 10): "foo"}

编辑:我以为你想要一个列表作为键。否则,你需要做到:

>>> import numpy as np
>>> keys = np.arange(10,dtype=int)
>>> values = np.arange(3,13)
>>> d = dict(numpy.array([keys,values]).T)
>>> d
{0: 3, 1: 4, 2: 5, 3: 6, 4: 7, 5: 8, 6: 9, 7: 10, 8: 11, 9: 12}
于 2013-08-28T14:48:51.520 回答
0

mabey 你可以按照这个思路做一些事情:

class my_dict(dict):
    def __getitem__(self, a):
        return dict.__getitem__(self, (a-1) / 10)
    def __setitem__(self, a, b):
        dict.__setitem__(self, (a-1) / 10, b)

dict_instance = my_dict()
dict_instance[1] = 'foo'
print dict_instance[9] # prints foo

dict_instance[17] = 'bar'
print dict_instance[12] # prints bar

这具有与普通 dict (O(1)) 一样快的蜜蜂的优势,但要小 10 倍

如果您希望它打印范围,您还需要覆盖 __ str__ ,您还可以使用这种数据类型非常容易地循环遍历唯一键:)

于 2013-08-28T15:04:19.083 回答