코드가 너무 느린 이유의 큰 부분은 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
이것을 쓸 수 있습니다.)
그리고 그 수단을 in issuesFound:
대신 if line not in issuesFoundCounter:
을 검색하면됩니다. 이미 dict
이므로 효과적으로 검색 할 수 있습니다. 그러나 setdefault
을 사용하거나 dict
대신 defaultdict
또는 Counter
을 사용하면 더 간단 해집니다.
for newLogLine in newLogFile:
for line in knownIssues:
if line in newLogLine:
issuesFoundCounter[line] += 1
그리고 당신은 내 빠른 루프와 파이썬에서 느린 틱 명시 적 루프를 제거, 발전기 식으로 그것을 켤 수 있습니다 :
그래서 issuesFoundCounter
가 Counter
경우, 모든 일이에 감소 통역관 배짱. 이것은 단지, 말, 고정 5가 될 것입니다 : 전반에서 선형 - 투 - 일정한 속도 향상에 반대, 1 속도 향상,하지만 고려 여전히 가치 :
이
issuesFoundCounter = collections.Counter(line
for newLogLine in newLogFile
for line in knownIssues
if line in newLogLine)
이 유일한 문제는 issuesFound
목록은 문제가 발견 된 순서가 아니라 임의의 순서로 표시됩니다. 중요하다면 Counter
대신 OrderedCounter
을 사용하면됩니다. 거기 collections
문서에 간단한 조리법은, 그러나 귀하의 경우에, 그것은 간단 할 수 있습니다
class OrderedCounter(Counter, OrderedDict):
pass
왜 당신이 붙박이 리눅스 명령을 사용하지 않는? 뭔가 grep, awk 및 wc 마법을 사용하여 무엇입니까? – Ben
내 일을하면서 우리는 많은 리눅스가이 모든 것을 기록하고있다.문제의 성격에 따라 특정 그룹의 정보를 필터링하고 grep 등으로 좋지 않은 하위 팀으로 필터링 된 로그를 전달할 수 있기를 희망했습니다. – user1678432
부수적으로 이와 같이 명시 적 카운터를 반복하면 코드를 읽기가 더 어려워집니다. 외부 루프를위한'newLogLine for newLogFile :'만이 아니겠습니까? – abarnert