Python 在字典中查找关键字的最快方法
我有一个字典,有超过1100万个键(每个值都是一个列表),每个键都是一个唯一的整数 e、 g 然后,我有一个单独的范围列表,例如。 [10-20,30-40,50-60] 我想说的是,对于我的范围列表中的每个范围,检查字典并返回值,如果键在范围内 因此,它将返回:Python 在字典中查找关键字的最快方法,python,performance,loops,dictionary,key,Python,Performance,Loops,Dictionary,Key,我有一个字典,有超过1100万个键(每个值都是一个列表),每个键都是一个唯一的整数 e、 g 然后,我有一个单独的范围列表,例如。 [10-20,30-40,50-60] 我想说的是,对于我的范围列表中的每个范围,检查字典并返回值,如果键在范围内 因此,它将返回: 10-20: "a","b" 50-60: "d" 我使用的实际代码是: for each_key in sorted(dictionary): if each_key in range(star
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万个键,并检查它是否在范围内
有没有一种方法可以让我说“跳过所有的字典键,直到发现其中一个高于起始数字”,然后“结束数字高于键时停止”?基本上就是以某种方式快速放大字典中某个范围内的部分
谢谢只需使用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循环中使用它很有用,在这种情况下没有缺点 我对这个问题的想法是先找到正确的钥匙。解决方案花费太多时间的原因是它使用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)
def二进制搜索(列表,目标):
左=0
右=len(alist)-1
如果目标>列表[-1]:
返回len(alist)
当左<右:
m=(左+右)/2
如果alist[m]==目标:
返回m
如果列表[m]<目标:
左=m+1
其他:
右=m
左转
def工作(字典、开始、结束):
keys=已排序(dictionary.keys())
开始位置=二进制搜索(键,开始)
end_pos=binarySearch(键,结束)
为范围内的pos(开始位置、结束位置)打印[字典[键[pos]]
字典={11:“a”,12:“b”,22:“c”,56:“d”}
工作(字典,10,20)
工作(字典,20,40)
工作(字典,10,60)
此解决方案(使用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())
从集合导入订单数据
d={2:3,10:89,4:5,23:0}
od=OrderedDict(已排序(d.items()))
lst=[“1-10”、“11-20”、“21-30”]
lower_lst=map(int,[i.split(“-”[0]表示lst中的i])
上_lst=map(int,[i.split(“-”[1]表示lst中的i])
对于低、上拉链(下拉链、上拉链):
打印“在范围{0}-{1}”中。格式(低,上),过滤器(lambda a:对我来说很低,效率极低。如果范围是1-1000000
,并且只存在200
,该怎么办?理论上,这将是一个问题,但OP有相反的问题,很多键,试图访问一个小数字。该方法删除了它们过于昂贵的循环,并对所有键进行排序,而是基于sma他们需要检查10个数字范围。如果范围太大,xrange而不是range会有更好的效果performance@Hadrián字典很大,范围却不大。虽然没有理由不在这里使用xrange,所以我将在sorted(字典)中编辑它
,就像字典一样,它什么也不做unordered@AhsanulHaque实际上,这将返回字典中键的排序列表。这可能有助于找到相关的范围,但它没有被利用。排序和创建一个包含1100万键的OrderedDict
不是需要很长时间吗?我需要付费我喜欢OP的初始排序是他们时间问题的一部分。
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())