2011-01-11 6 views
3

필자는 Python을 처음 접했을 때 독점적 인 마크 업 형식간에 변환하는 일련의 스크립트를 작성하고 있습니다. 내가 파일을 통해 라인으로 라인을 반복 한 후 기본적으로 기본적으로 4 종류로 분류 그 대체의 큰 번호 (100-200)를하고 있어요 :Python에서 많은 수의 검색/대체를 효율적으로 수행 할 수 있습니까?

line = line.replace("-","<EMDASH>") # Replace single character with tag 
line = line.replace("<\\@>","@")  # tag with single character 
line = line.replace("<\\n>","")  # remove tag 
line = line.replace("\xe1","&bull;") # replace non-ascii character with entity 

str.replace() 함수는 (매우 효율적인 것 같다 프로파일 링 출력을 조사 할 때 숫자가 상당히 낮습니다). 그러나 이것을 수행하는 더 좋은 방법이 있습니까? 함수로 인수로 re.sub() 메서드를 본 적이 있지만 이것이 더 좋을지 확실하지 않습니까? 파이썬이 내부적으로 어떤 종류의 최적화를하는지에 달려 있다고 생각합니다. 별로 도움이되지 않을 수도있는 큰 dict을 만들기 전에 몇 가지 조언을 요청할 것입니다.

또한 HTML (HTML과 비슷하지만 HTML이 아닌) 태그를 파싱합니다. ~ 100 검색/여기 효율성

m = re.findall('(<[^>]+>)',line) 
for tag in m: 
    tag_new = re.sub("\*t\([^\)]*\)","",tag) 
    tag_new = re.sub("\*p\([^\)]*\)","",tag_new) 

    # do many more searches... 

if tag != tag_new: 
    line = line.replace(tag,tag_new,1) # potentially problematic 

어떤 생각 : 예컨대,뿐만 아니라 일치하는 태그 내에서 (주로 경기를 제거)를 대체 한 후 않습니다

m = re.findall('(<[^>]+>)',line) 

그리고 :이 같은 태그를 식별?

감사합니다.

답변

3

str.replace()은 기본 검색을 수행 할 때 더 효율적이며 복잡한 패턴 매칭이 필요한 경우 re.sub이 더 효율적입니다 (그렇지 않으면 str.replace을 여러 번 사용해야하기 때문에).

두 가지를 함께 사용하는 것이 좋습니다. 한 패턴으로 대체되는 패턴이 여러 개인 경우 re.sub을 사용하십시오. 하나의 특정 태그를 다른 태그로 대체해야하는 경우에는 str.replace을 사용하십시오.

큰 문자열을 사용하여 효율성을 향상시킬 수도 있습니다 (각 줄마다 한 번만 대신 re.sub을 호출하십시오). 메모리 사용량은 증가하지만 파일이 커지지 않으면 문제가되지 않지만 실행 시간도 향상됩니다.

0

실제로 정규 표현식이 필요하지 않고 리터럴 대체 만 수행하는 경우 string.replace()가 더 빠를 것입니다. 그러나 그렇더라도 병목 현상은 문자열 입력이 아닌 파일 입력/출력이됩니다.

가장 좋은 해결책은하지만 아마 당신이에 운영하고있는 텍스트의 관련 - 투 - 관련이없는 부분의 비율에 따라 cStringIO

0

를 사용하는 것 (및 부품 여부를 각 대체에 운영 오버랩), 토큰 입력을 세분화하여 각 토큰에 개별적으로 작업하는 것이 더 효율적일 수 있습니다.

현재 구현의 각 replace()는 전체 입력 문자열을 검사해야하므로 속도가 느려질 수 있습니다. 대신 같은 뭔가에 그 스트림 ...

[<normal text>, <tag>, <tag>, <normal text>, <tag>, <normal text>] 
# from an original "<normal text><tag><tag><normal text><tag><normal text>" 

을 돌파하면 ... 당신은 단순히 주어진 토큰이 태그 있는지 볼 수 있고,에서 다음 ''.join()을 목록에서 대체 (그리고 종료).예를 들어 물론

>>> r = re.compile(r'<(\w+)>|(-)') 
>>> r.sub(lambda m: '(%s)' % (m.group(1) if m.group(1) else 'emdash'), '<atag>-<anothertag>') 
'(atag)(emdash)(anothertag)' 

은 더 복잡한 함수 객체를 사용할 수 있도록

당신은 대신 대체 문자열의 re.sub에 함수 객체를 전달할 수
0

는,이는 경기 객체를 사용하여 대체를 반환 람다는 단지 예일뿐입니다.

모든 대체를 수행하는 단일 정규식을 사용하면 문자열을 여러 번 반복하는 것보다 약간 빠르지 만 많은 대체가 수행되는 경우 대체를 계산하는 함수 개체를 호출하는 오버 헤드가 중요 할 수 있습니다.

관련 문제