2016-12-06 3 views
0

많은 단어를 사용하여 각 단어를 문자로 분리하고 큰 목록에 첨부하는 루프가 있습니다. 발생루프 실행 시간 단축 및 효율성 향상

list[0] = 편지 :

그때 가장 발생 문자를 확인하고, 이미 문자열에 표시되지 않는 경우에, 나는 두 개의 공백이 목록에 저장됩니다 이 루프는 매우 비효율적이다

발생 횟수를 가장

list[1]는 =. 작동하지만 값을 반환하는 데 약 25 ~ 30 초가 걸립니다. 그 전에는 계속 될 것이고 어떤 값도 반환하지 않을 것입니다.

내가 작성한 코드의 효율성을 높이려면 어떻게해야합니까?

def choose_letter(words, pattern): 
    list_of_letters = [] 
    first_letter = [] # first spot is the letter, second is how many times it appears 
    second_letter =[] # first spot is letter, second how many times it appears 
    max_appearances = ["letter", 0] 
    for i in range(len(words)): # splits up every word into letters 
     list_of_letters.append(list(words[i])) 
    list_of_letters = sum(list_of_letters, []) # concatenates the lists within the list 
    first_letter = list_of_letters.count(0) 
    for j in list_of_letters: 
     second_letter = list_of_letters.count(j) 
     if second_letter >= max_appearances[1] and j not in pattern: 
      max_appearances[0] = j 
      max_appearances[1] = second_letter 
     else: 
      list_of_letters.remove(j) 
    return max_appearances[0] 
+2

이것은 http : //codereview.stackexchange.com/ – Blorgbeard

+1

의 더 나은 후보가 될 수 있으며 codereview로 이동하면이 코드에 대해 실행 한 프로필러의 출력을 확인하게됩니다. –

+2

['collections.Counter'] (https://docs.python.org/3.5/library/collections.html#collections.Counter)에 대한 작업처럼 보입니다. – bereal

답변

0

더 빠르게 진행하는 한 가지 방법은 더 나은 데이터 구조를 선택하는 것입니다. 여기 collections.Counter를 사용하는 예입니다 : 당신은 당신이 필요로하지 않는 & 조작 목록을 루프를 많이하고있는

from collections import defaultdict 

def choose_letter(words, pattern): 
    pattern = set(pattern) 
    counts = defaultdict(int) 
    for word in words: 
     for letter in word: 
      if letter not in pattern: 
       counts[letter] += 1 
    return max(counts, key=counts.get) 

mywords = 'a man a plan a canal panama'.split() 
vowels = 'aeiou' 
assert choose_letter(mywords, vowels) == 'n' 
0

:

여기
from collections import Counter 

def choose_letter(words, pattern): 
    pattern = set(pattern) 
    letters = (letter 
       for word in words 
       for letter in word 
       if letter not in pattern) 
    letters = Counter(letters) 
    return letters.most_common(1)[0][0] 


mywords = 'a man a plan a canal panama'.split() 
vowels = 'aeiou' 
assert choose_letter(mywords, vowels) == 'n' 

collections.defaultdict를 사용하여 하나입니다. count 또는 not in을 실행할 때마다 프로그램은 목록/문자열을 반복하여 찾고있는 것을 찾습니다. 당신의 명부에서 그 품목 전부를 제거하는 것은 또한 꽤 비싸다. 훨씬 더 우아한 해결책은 단어/문자 목록을 한 번만 반복 한 다음 사전을 사용하여 각 문자의 개수를 계산하는 것입니다. 거기에서 문자/개수 쌍을 가진 사전을 가지고 있습니다. & 그곳에서 키/값을 얻을 수 있습니다. 목록을 정렬하면 & 처음 두 값을 봅니다.

count_dict = {} 
for word in words: 
    for char in word: 
     count_dict[char] = count_dict.get(char, 0) + 1 

을 ... 당신은 풀고 인수 파고 시도하지 않으려는 경우 :

from collections import defaultdict 
from itertools import chain 

def choose_letter(words, pattern=""): 
    count_dict = defaultdict(int) # all unknown values default to 0 
    for c in chain(*words): 
     count_dict[c] += 1 
    # you could replace this "not in" with something more efficient 
    filtered = [(char, count) for (char,count) in count_dict.items() if char not in pattern] 
    filtered.sort(lambda a,b: -cmp(a[0], b[0])) 
    print filtered 
    return filtered[0][0] 

당신이 인수 풀기 파고하지 않으려면, 당신은 말할 단지 수 & defaultdicts을 itertools 아직.