使算法更快,可以在多个列表上运行

时间:2014-11-29 15:20:49

标签: performance python-2.7 nested-loops

我正在编写一些具有嵌套循环的函数,当涉及大型列表时它会非常慢。

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

我希望这个解释得足够多。只要问你是否不明白我在这里想做什么。

谢谢

1 个答案:

答案 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