2013-12-08 3 views
3

파이썬 2.7 및 Levenshtein 함수를 사용하여 성의 목록을 성명의 목록과 일치 시키려고합니다. 작업량을 줄이기 위해 첫 글자가 동일한 경우에만 일치합니다 (성능상의 차이는별로 없지만). 일치하는 단어가 있으면 일치하는 단어가 전체 이름에서 제거됩니다. 두 목록 모두 수만 개의 항목을 포함하므로 내 솔루션이 다소 느립니다. 전체 이름을 파싱하지 않고 어떻게 처리 할 수 ​​있습니까? 어떤 도움을 주시면 감사하겠습니다파이썬, 중첩 된 루프, 일치 및 성능

import Levenshtein 

listoflastnames=(['Jones', 'Sallah']) 
listoffullnames=(['Henry', 'Jones', 'Junior'],['Indiana', 'Jones']) 


def match_strings(lastname, listofnames): 
    match=0 
    matchedidx=[] 
     for index, nameelement in enumerate(listofnames):   
      if lastname[0]==nameelement [0]: 
       if Levenshtein.distance(nameelement, lastname)<2: 
        matchedidx.append(index) 
        match=match+1 
    if match==1: 
     newnamelist = [i for j, i in enumerate(listofnames) if j not in matchedidx] 
    return 1, newnamelist 
return 0, listofnames 



for x in listoflastnames: 
    for y in listoffullnames: 
     match, newlistofnames=match_strings(x,y) 
     if match==1: 
      #go to first name match... 

: 여기 는 지금까지합니다 (라스트 네임이 여러 단어로 구성되어 경우에 나는 생략 한 몇 가지 경우 - 조건)가 무엇인가!

업데이트 : 그동안 다중 처리 모듈을 사용하여 4 개의 코어 모두를 문제가 아닌 하나의 문제 만 처리하도록했습니다. 그러나 여전히 일치하는 작업에는 많은 시간이 걸립니다.

+0

'levenenshtein.distance (g, publastnames [0]' 여기에 g와 publastnames [0]은 무엇입니까? – M4rtini

+0

죄송합니다. 이전 버전에서 남은 부분이었습니다 .Levenshtein 함수는 성을 비교합니다. – MrFancypants

+1

첫 번째 글자가 같은 곳에서만 계산을 수행하려는 경우 목록을 첫 번째 글자로 색인 된 사전으로 나눌 수 있습니다. 그런 다음 수행 할 수 있습니다. 모든 사람들이 아닌 실행 가능한 후보자 들간의 비교만으로도 성과를 향상시킬 수 있는지 여부는 거리 계산과는 대조적으로이 오버 헤드에 소요되는 시간의 양에 따라 다릅니다 – DSM

답변

1

이 코드는 match_string 함수의 루프를 단순화하지만 테스트에서 속도가 크게 증가하지는 않습니다. 가장 큰 손실은 성 및 성을 가진 두 개의 for 루프입니다.

def match_strings(lastname, listofnames): 
    firstCaseMatched = [name for name in listofnames if lastname[0] == name[0]] 
    if len(firstCaseMatched): 
     matchedidx = [index for index, ame in enumerate(firstCaseMatched) if Levenshtein.distance(lastname, name) < 2] 
     match = len(matchedidx) 
    else: 
     match = 0 
    if match == 1: 
     newnamelist = [i for j, i in enumerate(listofnames) if j not in matchedidx] 
     return 1, newnamelist 
    return 0, listofnames 

당신은, 알려진 마지막 이름의 목록을 정렬 각각의 시작 문자에 대한 dict로 분할해야 할 수 있습니다. 그런 다음 이름 목록의 각 이름과 일치시킵니다.

전체 이름 목록에는 항상 첫 번째 요소의 첫 번째 이름이 있다고 가정합니다. 비교를 다른 요소로만 제한 할 수 있습니다.

+0

귀하의 제안에 감사드립니다. 나는 lastnames를 첫 글자가 제안 된대로 키로 쪼개었다. 멀티 프로세싱과 함께 스크립트는 이제 원래 버전보다 약 20 배 빠릅니다. – MrFancypants

+0

Btw, 철자가 틀릴 수 있으므로 Levenshtein 거리를 사용한다고 가정하십니까? 이름의 첫 글자가 맞다는 것을 확신 할 수 있습니까? – M4rtini

+0

확신 할 수는 없지만 첫 번째 문자가 내 데이터의 하위 집합과 일치하는 경우를 제외하지 않고 스크립트를 테스트했을 때 오탐 (false positives)이 많이 도입 된 것처럼 보였습니다. 결과 세트에서 오탐을 수동으로 제거해야하므로 약간 낮은 리콜 속도를 기꺼이 받아 들일 수 있습니다 :) – MrFancypants