Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在字典中查找关键字的最快方法_Python_Performance_Loops_Dictionary_Key - Fatal编程技术网

Python 在字典中查找关键字的最快方法

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

我有一个字典,有超过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(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())