2017-05-07 138 views
10

我目前文件正在与超过200万线。我已将行分隔为元素列表(例如:[a,b,c,d] = 1行,单词分隔)。Python的循环优化

我尝试使用下面的代码要经过所有行:

for a in aud: 
    for esps in final: 
     if a[0] in final[esps]: 
      a[0] = esps 

在第一个for循环,我指的是200万条+线。在第二个for循环中,它通过一个带有2010键的字典,每个键可能至少有50个相应的值。我想在等于字典中的值的行中找到a[0]元素。如果它们匹配,则将所选行中的a[0]元素更改为字典的键值。

的问题是,这种代码需要年龄运行,我不明白太多(没有),有关优化,以及如何以更快的速度运行此。 如果有人能告诉我如何更快地做这样的事情,我会非常感谢。

+0

嗯,你只限于一台电脑?我想你可以用几个工人来做到这一点。即使只使用一台计算机,也可以使用多核CPU创建多个工作人员 –

+0

在没有任何示例数据的情况下,要解决您的实际问题有点难。每个“最终”字典字符串中的所有50个密钥都是? – jsbueno

+0

在迭代它的时候会不会有一个变异对象的副作用? – pylang

回答

24

当你有“大”的东西贯穿,类似这样的,关键要得到的东西去快是“减少算法的复杂性” - 也就是说,避免依赖于任何数据如果可能集的大小任何操作。

在你给的例子,你执行,为您的每一个百万行的50×2000线性搜索 - 这是一个很大!问题是,如果每个final[esps]的是一个列表,Python的执行在这50个值的线性搜索 - 与运营商in

既然你提到你正在从文件中读取你的值,我不得不假设012 [0]和final行中的元素都是字符串 - 但这也适用于数字。

第一个非常简单的优化,是简单地改变从列表对final字典行到set秒 - 从in操作者变更了比赛用set从是线性的,以在恒定的时间(从O(m)至O(1)) - 所以,你基本上是50倍,如果在你的榜样运行的代码之前削减你的搜索时间,你这样做:

for key in final: 
    final[key] = set(final[key]) 

但你依然表现在每一个2010的线性搜索钥匙final。更改为不断寻求的方法是创建一个颠倒的字典 - 其中每50个值的final点的一排按键esp代替。然后,您只需在此反转字典中使用[0]作为关键字 - 并且您正在替换100000个项目(2000 x 50)中的线性搜索,以便在字典中以恒定时间进行搜索;

这是很容易做到 - 只要改变你的代码:

rfinal = {} 
for esp, values in final.items(): 
    for value in values: 
     rfinal[value] = esp 


for a in aud: 
    if a[0] in rfinal: 
     a[0] = rfinal[a[0]] 
    else: 
     # code for when there is no match for a[0] 
     ... 
+2

这个例子改变了一切。从超过1小时没有完成...到仅仅几秒钟。这非常有帮助!通过我的工作和理解未来如何优化代码。谢谢你200万次以上! – Targaryel

+0

它只是大约100。在这种情况下快000倍:-) - 如果有效,请记得将答案标记为已接受。 – jsbueno

+2

实践这种优化问题的好地方是https://projecteuler.net/ – jsbueno