我正在编写一些具有嵌套循环的函数,当涉及大型列表时它会非常慢。
def get_resolved(urllist, generated_urls, layout):
result = {}
for url in urllist:
tmp_result = []
for gurl in generated_urls[url]:
if gurl in resolved[layout]:
tmp_result.append(gurl)
result[url] = tmp_result
return result
我在这个函数中有三个列表,一个包含大约5000个域名的列表urllist,一个包含大约500 000个项目的generated_urls列表,它们也只是文本,然后是第三个列表解析[layout]。最后一个列表来自已解析的全局字典。这个也平均包含10 000个项目。
我想返回一个结果字典,该字典仅包含该特定网址的generated_urls中的项目,该网址也位于已解析的[布局]列表中。
问题是这个嵌套循环需要大约一个小时才能执行。这是缓慢的,因为我必须这样做大约30次或其他什么。我不知道如何使这更高效。有谁知道我怎么能做到这一点?
我也在这个脚本上运行cProfile,这让我发现上面的脚本太慢了。 这是输出的最高部分:
Sat Nov 29 17:09:10 2014 profile_difflayouts
2684341 function calls (2684295 primitive calls) in 101.069 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.006 0.006 101.069 101.069 DiffLayouts.py:1(<module>)
1 0.001 0.001 101.055 101.055 DiffLayouts.py:13(main)
18 0.001 0.000 95.898 5.328 DiffLayouts.py:62(process_data)
36 95.712 2.659 95.712 2.659 DiffLayouts.py:149(get_resolved)
1 0.001 0.001 79.703 79.703 DiffLayouts.py:30(check_alexa_list_single)
1 0.000 0.000 16.198 16.198 DiffLayouts.py:42(check_alexa_list_combined)
3 0.950 0.317 5.152 1.717 DiffLayouts.py:136(filter_domainnames)
1017314 2.182 0.000 2.182 0.000 {method 'search' of '_sre.SRE_Pattern' objects}
775796 1.561 0.000 1.561 0.000 {method 'findall' of '_sre.SRE_Pattern' objects}
75 0.240 0.003 0.240 0.003 {method 'read' of 'file' objects}
75 0.115 0.002 0.115 0.002 {method 'splitlines' of 'str' objects}
这实际上是一些新代码,我已经尝试过了。列表理解,但这只给我一个非常小的性能增益约0.5%。 新版本:
def get_resolved(urllist, generated_urls, layout):
result = {}
for url in urllist:
result[url] = [x for x in generated_urls[url] if x in resolved[layout]]
return result
我希望这个解释得足够多。只要问你是否不明白我在这里想做什么。
谢谢
答案 0 :(得分:1)
从个人资料中可以看出,您花费了所有时间来检查if x in resolved[layout]
元素的成员资格。
现在,列表不是存储仅需要支持搜索的不可变对象集的最有效方法。 使用套装。考虑一下这个微观基准:
import random
import time
import sys
size_url = 10000
size_resolved = 10000
random.seed(time.time())
url = [ random.randint(1,sys.maxint) for x in xrange(size_url)]
resolved = [ random.randint(1,sys.maxint) for x in xrange(size_resolved)]
a = time.time()
intersection = [ x for x in url if x in resolved ]
print "Search in list:",time.time() - a
resolved = set(resolved)
a = time.time()
intersection = [ x for x in url if x in resolved ]
print "Search in set:",time.time() - a
这是我在笔记本电脑上输出的内容:
Search in list: 1.89044713974
Search in set: 0.00117897987366
因此,请按以下方式修改代码:
def get_resolved(urllist, generated_urls, layout):
result = {}
for url in urllist:
result[url] = [x for x in generated_urls[url] if x in set(resolved[layout])]
return result