2017-03-16 2 views
1

사용자가 오타를 만든 경우 사용자에게 플레이어 이름을 제안하는 프로그램입니다. 매우 느립니다.어떻게 코드를 빠르게 할 수 있습니까?

먼저 get 요청을 실행 한 다음 플레이어의 이름이 json 데이터 내에 있는지 확인합니다 (통과 한 경우). 그렇지 않으면 모든 선수의 성과 이름이 붙어 names에 추가됩니다. 그런 다음 first_namelast_nameget_close_matches을 사용하여 목록의 이름과 매우 유사한 지 확인합니다. 처음부터 이것이 매우 느릴 것이라는 것을 알았지 만, 이것을 수행하는 더 빠른 방법이 있어야했습니다. 단지 하나만 생각해 낼 수있었습니다. 어떤 제안?

from difflib import get_close_matches 
def suggestion(first_name, last_name): 
    names = [] 
    my_request = get_request("https://www.mysportsfeeds.com/api/feed/pull/nfl/2016-2017-regular/active_players.json") 

    for n in my_request['activeplayers']['playerentry']: 
     if last_name == n['player']['LastName'] and first_name == n['player']['FirstName']: 
      pass 

     else: 
      names.append(n['player']['FirstName'] + " " + n['player']['LastName']) 
      suggest = get_close_matches(first_name + " " + last_name, names) 

    return "did you mean " + "".join(suggest) + "?" 



print suggestion("mattthews ", "stafffford") #should return Matthew Stafford 
+0

당신은 다음 값에서 시작하여 다시 실행하는 루프를 알려줍니다 CONTINUE ''에'pass'을 변경할 수 있습니다 . –

+4

IO 시간을 줄이기 위해 [url] (https://www.mysportsfeeds.com/api/feed/pull/nfl/2016-2017-regular/active_players.json) 콘텐츠를 로컬에 보관하는 방법은 무엇입니까? –

+1

@OldPanda와 같은 줄에 따라 캐싱 전략을 구현하십시오. memcached와 같은 것을 이용할 수 있습니까? – dana

답변

1

의견에 대한 제 제안이 나왔기 때문에 다른 아이디어가 포함 된 답변으로 게시 할 수도 있습니다.

먼저 함수가 실행될 때마다 요청을하는 데 시간을 낭비하지 않도록 I/O 연산을 함수에서 제거하십시오. 대신 스크립트를 시작할 때 json을 가져 와서 로컬 메모리에로드합니다. 가능하다면 미리 json 데이터를 다운로드하고 대신 텍스트 파일을 여는 것이 더 빠를 수 있습니다.

둘째, 여러 번 비교할 필요가 없으므로 루프 당 고유 한 후보 집합을 가져야합니다. get_close_matches()으로 이름을 삭제하면 동일한 이름을 비교할 필요가 없습니다. . (이름이 삭제되는 기준이 후속 이름에 따라 다르면 다르 겠지만, 여기에 해당하는 것은 의심 스럽습니다.)

셋째, 일괄 작업을 시도해보십시오. get_close_matches()이 합리적으로 효율적이라는 점을 감안할 때, 한 번에 10 명의 후보자가 1 명보다 느려서는 안됩니다. 그러나 for 루프가 100 만 개가 넘는 요소에서 100,000 개가 넘는 요소로 이동하는 것은 큰 도움이됩니다.

넷째, 나는이 경우에 오타가 없었기 때문에 last_name == ['LastName'] and first_name == ['FirstName']을 확인한다고 가정합니다. 그렇다면 단순히 기능을 중단하지 않는 이유는 무엇입니까? 모두 함께 퍼팅

,이처럼 보이는 코드를 작성할 수 있습니다 :

from difflib import get_close_matches 

# I/O operation ONCE when the script is run 
my_request = get_request("https://www.mysportsfeeds.com/api/feed/pull/nfl/2016-2017-regular/active_players.json") 

# Creating batches of 10 names; this also happens only once 
# As a result, the script might take longer to load but run faster. 
# I'm sure there is a better way to create batches, but I'm don't know any. 
batch = [] # This will contain 10 names. 
names = [] # This will contain the batches. 

for player in my_request['activeplayers']['playerentry']: 
    name = player['FirstName'] + " " + player['LastName'] 
    batch.append(name) 

    # Obviously, if the number of names is not a multiple of 10, this won't work! 
    if len(batch) == 10: 
     names.append(batch) 
     batch = [] 

def suggest(first_name, last_name, names): 

    desired_name = first_name + " " + last_name 
    suggestions = [] 

    for batch in names: 

     # Just print the name if there is no typo 
     # Alternatively, you can create a flat list of names outside of the function 
     # and see if the desired_name is in the list of names to immediately 
     # terminate the function. But I'm not sure which method is faster. It's 
     # a quick profiling task for you, though. 
     if desired_name in batch: 
      return desired_name 

     # This way, we only match with new candidates, 10 at a time. 
     best_matches = get_close_matches(desired_name, batch) 
     suggestions.append(best_matches) 

    # We need to flatten the list of suggestions to print. 
    # Alternatively, you could use a for loop to append in the first place. 
    suggestions = [name for batch in suggestions for name in batch] 

    return "did you mean " + ", ".join(suggestions) + "?" 

print suggestion("mattthews ", "stafffford") #should return Matthew Stafford 
관련 문제