python中的关联数组,键作为数组的片段

时间:2014-07-28 20:10:30

标签: python arrays

如何更好地实施这样的事情:

循环数字。 diapason中的每个数字都属于关联数组的一部分。

E.g。

 di = {}
 di[ xrange(0,10) ] = "A"
 di[ xrange(11,20) ] = "B"
 di[ xrange(21,30) ] = "C"

 direction = di[ 24 ]
 # direction should be "C"

 direction = di[ 6 ]
 # direction should be "A"

编辑使用谨慎的数字填充整个di不是我的方式,因为我说的是IP地址,真正的大数据,例如netmasks 255.255.255.255。这样的di会溢出我的RAM。

4 个答案:

答案 0 :(得分:1)

我会创建一个以xrange为键的自定义词典:

class DictRange(dict):
    def __getitem__(self, val):
        for key in self.keys():
            if val in key:
                return super(DictRange,self).__getitem__(key)

缺点是您必须通过所有键才能找到您的元素。使用那样:

di = DictRange()
di[ xrange(0,10) ] = "A"
di[ xrange(11,20) ] = "B"
di[ xrange(21,30) ] = "C"

print di[24]
# C
print di[6]
# A

请参阅http://repl.it/WAJ

更新

使用bisect并假设您可以在初始化期间节省一些时间以加快访问速度,您可以执行以下操作:

import bisect
class DictRange(dict):

    def __setitem__(self, key, val):
        super(DictRange,self).__setitem__(key, val)
        self.ks = [key[0] for key in self.keys()]

    def __getitem__(self, val):
        return super(DictRange,self).__getitem__(self.keys()[bisect.bisect(self.ks, val) - 1])

获取将为O(logn),其中n是键的数量,但该组将变为O(n)。至于下一个解决方案,它依赖于连续的范围。

其他解决方案

另一种解决方案可能会更快,具体取决于您的范围大小,将用作关键字范围的第一项,以及一个二等分来找到正确的关键字:

import bisect
ranges = [0, 11, 21, 31]
di = {}
di[0] = 'A'
di[11] = 'B'
di[21] = 'C'
di[31] = 'unknown' # special value to indicate the end of the range

print di[ranges[bisect.bisect(ranges, 24) - 1]]
# C
print di[ranges[bisect.bisect(ranges, 6) - 1]]
# A
print di[ranges[bisect.bisect(ranges, 31) - 1]]
# Unknown

这会快得多。 bisectO(logn),其中n是范围数,其余为O(1)

答案 1 :(得分:0)

如果您不想填写字典,只需使用一个函数

from __future__ import division
import string
def return_ltr(i):
    n = i//10 
    return string.ascii_uppercase[n]

否则,如果要填充字典,请执行以下操作。您当前的代码正在生成xrange objects并将其用作键。但是,这与使用键的数字不同。请尝试以下方法,

import string
d = {}
i = 0
for ltr in string.ascii_uppercase:
    for j in xrange(10):
        d[i] = ltr
        i += 1

如果您只想要字母的子集,则可以切片string.ascii_uppercase。例如,使用string.ascii_uppercase[0:3]只会为您提供ABC

答案 2 :(得分:0)

di = dict.fromkeys(xrange(0, 10), 'A')
di.update(dict.fromkeys(xrange(10, 20), 'B'))
di.update(dict.fromkeys(xrange(20, 30), 'C'))
print(di)

产量

{0: 'A', 1: 'A', 2: 'A', 3: 'A', 4: 'A', 5: 'A', 6: 'A', 7: 'A', 8: 'A', 9: 'A', 10: 'B', 11: 'B', 12: 'B', 13: 'B', 14: 'B', 15: 'B', 16: 'B', 17: 'B', 18: 'B', 19: 'B', 20: 'C', 21: 'C', 22: 'C', 23: 'C', 24: 'C', 25: 'C', 26: 'C', 27: 'C', 28: 'C', 29: 'C'}

请注意xrange(N, M)生成从N开始到M-1(包括)结尾的整数。因此,如果您想在密钥中包含10,20,则xrange应为xrange(10, 20)xrange(20, 30)

答案 3 :(得分:0)

您可以使用元组而不是列表来解决TypeError(您的代码不会引发FWIW),但查找仍然不起作用。可能最有效的方法是用给定值的每个离散键填充dict,即:

map = (
   (0, 10, "A"),
   (11, 20, "B"),
   # etc
   )

d = {}
for start, stop, val in map:
   for k in xrange(start, stop):
       d[k] = val