我有一个字典,有超过1100万个键(每个值都是一个列表)。每个键是一个唯一的整数。
e.g。
Dict1 = {11:"a",12:"b",22:"c",56:"d"}
然后,另外,我有一个范围列表,例如 [10-20,30-40,50-60]
我想说,对于我的范围列表中的每个范围,如果密钥在范围内,请浏览字典并返回值。
所以它会回来:
10-20: "a","b"
50-60: "d"
我使用的实际代码是:
for each_key in sorted(dictionary):
if each_key in range(start,end):
print str(dictionary[each_key])
问题在于这种技术非常漫长,因为它通过了所有1100万个密钥并检查它是否在范围内。
有没有办法可以说“跳过所有字典键,直到找到一个高于起始编号的字典”然后“一旦结束数字高于密钥就停止”?基本上只是某种方式可以很快地在一定范围内放大字典部分?
由于
答案 0 :(得分:2)
只需使用Python的EAFP原则。请求宽恕比允许更容易。
假设所有密钥都有效,如果不是,则捕获错误:
for key in xrange(start, end):
try:
print str(dictionary[key])
except KeyError:
pass
这只会尝试将每个数字作为一个键,如果有一个KeyError
来自一个不存在的键,那么它将继续进行下一次迭代。
请注意,如果您预计会丢失很多密钥,那么首先测试可能会更快:
for key in xrange(start, end):
if key in dictionary:
print str(dictionary[key])
请注意,xrange
与range
的功能略有不同。它将逐个生成值,而不是提前创建整个列表。在for循环中使用它是有用的,在这种情况下没有缺点。
答案 1 :(得分:0)
我对这个问题的想法是先找到正确的密钥。您的解决方案花费太多时间的原因是它使用O(n)算法来查找正确的密钥。如果我们可以实现二进制搜索方法,复杂性将降低到O(log(n)),这有很大帮助。
以下是我的示例代码。它适用于这个例子,但我不能保证它不会得到一些小错误。只需在那里找到想法并实施你的想法。
def binarySearch(alist, target):
left = 0
right = len(alist) -1
if target>alist[-1]:
return len(alist)
while left < right:
m = (left + right) / 2
if alist[m] == target:
return m
if alist[m] < target:
left = m+1
else:
right = m
return left
def work(dictionary, start, end):
keys = sorted(dictionary.keys())
start_pos = binarySearch(keys, start)
end_pos = binarySearch(keys, end)
print [dictionary[keys[pos]] for pos in range(start_pos,end_pos)]
dictionary = {11:"a",12:"b",22:"c",56:"d"}
work(dictionary, 10, 20)
work(dictionary, 20, 40)
work(dictionary, 10, 60)
答案 2 :(得分:-1)
此解决方案(使用OrderedDict和过滤器)可以帮助您。
from collections import OrderedDict
d = {2:3, 10:89, 4:5, 23:0}
od = OrderedDict(sorted(d.items()))
lst=["1-10","11-20","21-30"]
lower_lst=map(int,[i.split("-")[0] for i in lst])
upper_lst=map(int,[i.split("-")[1] for i in lst])
for low,up in zip(lower_lst,upper_lst):
print "In range {0}-{1}".format(low,up),filter(lambda a:low <= a[0] <= up,od.iteritems())