2014-01-14 112 views
3

我有以下代碼:循環性能下降

keywordindex = cPickle.load(open('keywordindex.p','rb'))#contains~340 thousand items 
masterIndex = {} 

indexes = [keywordindex] 
for partialIndex in indexes: 
    start = time.time() 
    for key in partialIndex.iterkeys(): 
     if key not in masterIndex.keys(): 
      masterIndex[key]= partialIndex[key] 
     elif key in masterIndex.keys(): 
      masterIndex[key].extend(partialIndex[key]) 
    cPickle.dump(masterIndex,open('MasterIndex.p','wb')) 

    print int(time.time() - start), ' seconds'#every thousand loops 

和我遇到降解性能,循環運行,前10萬餘耗時5秒左右‰,但每10萬人左右,另需第二,直到它的時間延長3倍。我試圖以各種可能的方式簡化代碼,但我似乎無法弄清楚是什麼原因造成的。是否有一個原因?這不是一個內存問題,我只有30%的使用率

+0

你爲什麼要創建一個1元素的索引列表,然後遍歷它呢?看起來你可以完全拋棄外部循環。 – user2357112

+0

@user有超過1個的列表,我刪除了他們的問題 –

回答

8

此塊包含horridly低效編碼的兩個實例:

if key not in masterIndex.keys(): 
     masterIndex[key]= partialIndex[key] 
    elif key in masterIndex.keys(): 
     masterIndex[key].extend(partialIndex[key]) 

首先,關鍵是或不是masterIndex,所以沒有有用點在所有的測試elif。如果not in測試失敗,則in測試必須成功。所以,這個代碼是相同的:

if key not in masterIndex.keys(): 
     masterIndex[key]= partialIndex[key] 
    else: 
     masterIndex[key].extend(partialIndex[key]) 

其次,masterIndexdict。 Dicts支持非常高效的會員資格測試,而無需任何幫助;-)通過將其密鑰實現到列表中(通過.keys()),您可以將應該是快速的字典查找,並對列表進行可怕的慢速線性搜索。因此,請改爲:

if key not in masterIndex: 
     masterIndex[key]= partialIndex[key] 
    else: 
     masterIndex[key].extend(partialIndex[key]) 

代碼將運行得更快。

+1

看到你的答案類似於在街上看到名人。 –

+0

感謝您提供清晰簡潔的答案。我知道'elif'很糟糕,它早期剩下的,但我不知道'dict'的成員資格測試比'list' –

+0

@ChuckFulminata更快,會員測試是O(1),而線性搜索是O(n) –

3

你不需要通過masterIndex.keys()搜索。此外,只需要使用一個空else子句:

if key not in masterIndex: 
    ... 
else: 
    ... 

in的操作者上的字典查詢該字典和該操作的時間複雜度的鍵是O(1)上平均。

+0

'elif'是之前剩餘的,當我需要知道到底發生了什麼 –