的代碼是如此緩慢的一個重要原因,就是if line not in issuesFound:
。這需要通過一個巨大的列表進行線性搜索。
您可以通過添加set
看到的問題(這是有效的免費搜索)來解決該問題。這會將您的時間從O(NM)減少到O(N)。
但實際上,您可以通過完全刪除if
來簡化操作。
首先,您可以根據issuesFoundCounter
的鍵值生成issuesFound
列表。對於issuesFoundCounter
中的每一行,您需要該行,然後是其knownIssues[line]
。所以:
issuesFound = list(flatten((line, knownIssues[line]) for line in issuesFoundCounter))
(我使用從itertools
文檔的flatten
配方您可以複製到你的代碼,或者你可以寫這與itertools.chain.from_iterable
代替flatten
。)
,這意味着你可以搜索if line not in issuesFoundCounter:
而不是in issuesFound:
,這已經是dict
(因此可以有效地免費搜索)。但是,如果您只使用setdefault
- 或者更簡單,則可以使用defaultdict
或Counter
而不是dict
- 您可以自動進行此操作。
所以,如果issuesFoundCounter
是Counter
,整個事情簡化爲這樣:
for newLogLine in newLogFile:
for line in knownIssues:
if line in newLogLine:
issuesFoundCounter[line] += 1
而且你可以把它轉換成一臺發電機的表達,從而消除在Python緩慢上下的明確循環裏面的快循環口譯員的膽量。這只是將是,比如說,一個固定的5:1的加速,而不是從上半年的線性 - 不斷加速,但它仍然是值得考慮的:
issuesFoundCounter = collections.Counter(line
for newLogLine in newLogFile
for line in knownIssues
if line in newLogLine)
與此唯一的問題是issuesFound
列表現在按照任意順序排列,而不是按照發現問題的順序排列。如果這很重要,只需使用OrderedCounter
而不是Counter
。有一個簡單的配方在collections
文檔,但是對於你的情況,因爲它可以作爲簡單:
class OrderedCounter(Counter, OrderedDict):
pass
你爲什麼不使用內置的Linux命令?一些有點grep,awk和wc魔術? – Ben
隨着我的工作,我們在許多Linux日誌上工作,所有這些性質。希望能夠根據問題的性質過濾出某些信息組,然後將過濾的日誌傳遞給grep等不太好的較低的團隊。 – user1678432
作爲一個方面說明,像這樣的顯式計數器迭代會使代碼難以閱讀。爲什麼不爲'newLogFile中的newLogLine:'爲外部循環? – abarnert