2011-02-04 44 views
12

Tôi đang tìm cách nhanh nhất để thay thế một số lượng lớn các chuỗi con bên trong một chuỗi rất lớn. Dưới đây là hai ví dụ tôi đã sử dụng.Phương pháp Python nhanh nhất để tìm kiếm và thay thế trên một chuỗi lớn

findall() cảm thấy đơn giản và thanh lịch hơn, nhưng phải mất một khoảng thời gian đáng kinh ngạc.

công cụ tìm kiếm() thông qua một tệp lớn, nhưng tôi không chắc đây là cách phù hợp để thực hiện điều đó.

Dưới đây là một số mã mẫu. Lưu ý rằng văn bản thực tế mà tôi quan tâm là một chuỗi duy nhất có kích thước khoảng 10MB và có sự khác biệt lớn trong hai phương thức này.

import re 

def findall_replace(text, reg, rep): 
    for match in reg.findall(text): 
     output = text.replace(match, rep) 
    return output 

def finditer_replace(text, reg, rep): 
    cursor_pos = 0 
    output = '' 
    for match in reg.finditer(text): 
     output += "".join([text[cursor_pos:match.start(1)], rep]) 
     cursor_pos = match.end(1) 
    output += "".join([text[cursor_pos:]]) 
    return output 

reg = re.compile(r'(dog)') 
rep = 'cat' 
text = 'dog cat dog cat dog cat' 

finditer_replace(text, reg, rep) 

findall_replace(text, reg, rep) 

CẬP NHẬT Added phương pháp re.sub để kiểm tra:

def sub_replace(reg, rep, text): 
    output = re.sub(reg, rep, text) 
    return output 

Kết quả

re.sub() - 0: 00: 00.031000
finditer() - 0 : 00: 00.109000
findall() - 0: 01: 17.260000

+0

và điều thứ hai thực sự là nhanh hơn nhiều? Có vẻ lạ với tôi, họ nên dùng khoảng. cùng lúc. Và tôi nghĩ cả hai cách đều đúng. –

+0

tại sao bạn không sử dụng phương thức phụ của re? –

+1

Sử dụng + = với chuỗi là một hoạt động O (n^2), so với O (n) xây dựng danh sách và sử dụng "" để tham gia. –

Trả lời

14

Các phương pháp tiêu chuẩn là sử dụng được xây dựng trong

re.sub(reg, rep, text) 

Ngẫu nhiên lý do cho sự khác biệt về hiệu năng giữa các phiên bản của bạn là mỗi thay thế trong phiên bản đầu tiên của bạn sẽ làm cho toàn bộ chuỗi được recopied. Bản sao nhanh, nhưng khi bạn sao chép 10 MB khi đang di chuyển, đủ bản sao sẽ trở nên chậm.

+0

Cảm ơn bạn. Tôi đã không sử dụng re.sub() bởi vì tôi nghĩ rằng nó hoạt động trong cùng một là tìm kiếm. Tôi chạy thử nghiệm của tôi một lần nữa và re.sub rõ ràng là phương pháp nhanh nhất. Các kết quả đã được thêm vào câu hỏi. – cyrus

4

Bạn có thể, và tôi nghĩ rằng bạn phải bởi vì nó chắc chắn là một chức năng tối ưu hóa, sử dụng

re.sub(pattern, repl, string[, count, flags]) 

Lý do tại sao findall_replace của bạn() chức năng có chiều dài là ở mỗi trận đấu, một đối tượng chuỗi mới được tạo ra, vì bạn sẽ nhìn thấy bằng cách thực thi đoạn mã sau:

ch = '''qskfg qmohb561687ipuygvnjoihi2576871987uuiazpoieiohoihnoipoioh 
opuihbavarfgvipauhbi277auhpuitchpanbiuhbvtaoi541987ujptoihbepoihvpoezi 
abtvar473727tta aat tvatbvatzeouithvbop772iezubiuvpzhbepuv454524522ueh''' 

import re 

def findall_replace(text, reg, rep): 
    for match in reg.findall(text): 
     text = text.replace(match, rep) 
     print id(text) 
    return text 

pat = re.compile('\d+') 
rep = 'AAAAAAA' 

print id(ch) 
print 
print findall_replace(ch, pat, rep) 

Lưu ý rằng trong mã này tôi thay output = text.replace(match, rep) với text = text.replace(match, rep), nếu không chỉ sự xuất hiện cuối cùng được thay thế.

finditer_replace() là dài vì lý do tương tự như đối với findall_replace(): tạo lặp lại đối tượng chuỗi. Nhưng trước đây sử dụng một iterator re.finditer() trong khi cấu trúc thứ hai trở thành một đối tượng danh sách, vì vậy nó dài hơn. Đó là sự khác biệt giữa trình lặp và không lặp.

1

Bằng cách này, mã của bạn với findall_replace() là không an toàn, nó có thể trả lại kết quả unawaited:

ch = 'sea sun ABC-ABC-DEF bling ranch micABC-DEF fish' 

import re 

def findall_replace(text, reg, rep): 
    for gr in reg.findall(text): 
     text = text.replace(gr, rep) 
     print 'group==',gr 
     print 'text==',text 
    return '\nresult is : '+text 

pat = re.compile('ABC-DE') 
rep = 'DEFINITION' 

print 'ch==',ch 
print 
print findall_replace(ch, pat, rep) 

hiển thị

ch== sea sun ABC-ABC-DEF bling ranch micABC-DEF fish 

group== ABC-DE 
text== sea sun ABC-DEFINITIONF bling ranch micDEFINITIONF fish 
group== ABC-DE 
text== sea sun DEFINITIONFINITIONF bling ranch micDEFINITIONF fish 

result is : sea sun DEFINITIONFINITIONF bling ranch micDEFINITIONF fish 
Các vấn đề liên quan