Khi một cách xử lý văn bản phải được thực hiện để chỉ trích xuất dữ liệu từ nó, tôi luôn nghĩ trước tiên với Regexes, bởi vì:
Theo như tôi biết, regexes đã được phát minh cho điều đó
Lặp lại trên các dòng xuất hiện vụng về đối với tôi: về cơ bản nó bao gồm tìm kiếm các dòng mới sau đó để tìm kiếm dữ liệu để trích xuất trong mỗi dòng; Điều đó tạo ra hai tìm kiếm thay vì một tìm kiếm trực tiếp với một regex
Cách đưa Regexes vào chơi rất dễ dàng; Chỉ có việc viết một chuỗi regex được biên dịch thành một đối tượng regex đôi khi là khó khăn, nhưng trong trường hợp này, việc điều trị bằng một lần lặp trên các dòng cũng sẽ phức tạp
Đối với vấn đề được thảo luận ở đây, một giải pháp Regex rất nhanh và dễ viết:
import re
names = re.findall['\S+',open[filename].read[]]
Tôi đã so sánh tốc độ của một số giải pháp:
import re
from time import clock
A,AA,B1,B2,BS,reg = [],[],[],[],[],[]
D,Dsh,C1,C2 = [],[],[],[]
F1,F2,F3 = [],[],[]
def nonblank_lines[f]:
for l in f:
line = l.rstrip[]
if line: yield line
def short_nonblank_lines[f]:
for l in f:
line = l[0:-1]
if line: yield line
for essays in xrange[50]:
te = clock[]
with open['raa.txt'] as f:
names_listA = [line.strip[] for line in f if line.strip[]] # Felix Kling
A.append[clock[]-te]
te = clock[]
with open['raa.txt'] as f:
names_listAA = [line[0:-1] for line in f if line[0:-1]] # Felix Kling with line[0:-1]
AA.append[clock[]-te]
#-------------------------------------------------------
te = clock[]
with open['raa.txt'] as f_in:
namesB1 = [ name for name in [l.strip[] for l in f_in] if name ] # aaronasterling without list[]
B1.append[clock[]-te]
te = clock[]
with open['raa.txt'] as f_in:
namesB2 = [ name for name in [l[0:-1] for l in f_in] if name ] # aaronasterling without list[] and with line[0:-1]
B2.append[clock[]-te]
te = clock[]
with open['raa.txt'] as f_in:
namesBS = [ name for name in f_in.read[].splitlines[] if name ] # a list comprehension with read[].splitlines[]
BS.append[clock[]-te]
#-------------------------------------------------------
te = clock[]
with open['raa.txt'] as f:
xreg = re.findall['\S+',f.read[]] # eyquem
reg.append[clock[]-te]
#-------------------------------------------------------
te = clock[]
with open['raa.txt'] as f_in:
linesC1 = list[line for line in [l.strip[] for l in f_in] if line] # aaronasterling
C1.append[clock[]-te]
te = clock[]
with open['raa.txt'] as f_in:
linesC2 = list[line for line in [l[0:-1] for l in f_in] if line] # aaronasterling with line[0:-1]
C2.append[clock[]-te]
#-------------------------------------------------------
te = clock[]
with open['raa.txt'] as f_in:
yD = [ line for line in nonblank_lines[f_in] ] # aaronasterling update
D.append[clock[]-te]
te = clock[]
with open['raa.txt'] as f_in:
yDsh = [ name for name in short_nonblank_lines[f_in] ] # nonblank_lines with line[0:-1]
Dsh.append[clock[]-te]
#-------------------------------------------------------
te = clock[]
with open['raa.txt'] as f_in:
linesF1 = filter[None, [line.rstrip[] for line in f_in]] # aaronasterling update 2
F1.append[clock[]-te]
te = clock[]
with open['raa.txt'] as f_in:
linesF2 = filter[None, [line[0:-1] for line in f_in]] # aaronasterling update 2 with line[0:-1]
F2.append[clock[]-te]
te = clock[]
with open['raa.txt'] as f_in:
linesF3 = filter[None, f_in.read[].splitlines[]] # aaronasterling update 2 with read[].splitlines[]
F3.append[clock[]-te]
print 'names_listA == names_listAA==namesB1==namesB2==namesBS==xreg\n is ',\
names_listA == names_listAA==namesB1==namesB2==namesBS==xreg
print 'names_listA == yD==yDsh==linesC1==linesC2==linesF1==linesF2==linesF3\n is ',\
names_listA == yD==yDsh==linesC1==linesC2==linesF1==linesF2==linesF3,'\n\n\n'
def displ[[fr,it,what]]: print fr + str[ min[it] ][0:7] + ' ' + what
map[displ,[['* ', A, '[line.strip[] for line in f if line.strip[]] * Felix Kling\n'],
[' ', B1, ' [name for name in [l.strip[] for l in f_in] if name ] aaronasterling without list[]'],
['* ', C1, 'list[line for line in [l.strip[] for l in f_in] if line] * aaronasterling\n'],
['* ', reg, 're.findall["\S+",f.read[]] * eyquem\n'],
['* ', D, '[ line for line in nonblank_lines[f_in] ] * aaronasterling update'],
[' ', Dsh, '[ line for line in short_nonblank_lines[f_in] ] nonblank_lines with line[0:-1]\n'],
['* ', F1 , 'filter[None, [line.rstrip[] for line in f_in]] * aaronasterling update 2\n'],
[' ', B2, ' [name for name in [l[0:-1] for l in f_in] if name ] aaronasterling without list[] and with line[0:-1]'],
[' ', C2, 'list[line for line in [l[0:-1] for l in f_in] if line] aaronasterling with line[0:-1]\n'],
[' ', AA, '[line[0:-1] for line in f if line[0:-1] ] Felix Kling with line[0:-1]\n'],
[' ', BS, '[name for name in f_in.read[].splitlines[] if name ] a list comprehension with read[].splitlines[]\n'],
[' ', F2 , 'filter[None, [line[0:-1] for line in f_in]] aaronasterling update 2 with line[0:-1]'],
[' ', F3 , 'filter[None, f_in.read[].splitlines[] aaronasterling update 2 with read[].splitlines[]']]
]
Giải pháp với Regex là đơn giản và gọn gàng. Mặc dù vậy, nó không phải là một trong những người nhanh nhất. Giải pháp của Aaronasterling với Filter [] rất nhanh đối với tôi [tôi không biết về tốc độ của bộ lọc cụ thể này [] và thời gian của các giải pháp được tối ưu hóa giảm xuống cho đến 27 % thời gian lớn nhất. Tôi tự hỏi điều gì làm cho phép lạ của Hiệp hội bộ lọc-splitlines:
names_listA == names_listAA==namesB1==namesB2==namesBS==xreg
is True
names_listA == yD==yDsh==linesC1==linesC2==linesF1==linesF2==linesF3
is True
* 0.08266 [line.strip[] for line in f if line.strip[]] * Felix Kling
0.07535 [name for name in [l.strip[] for l in f_in] if name ] aaronasterling without list[]
* 0.06912 list[line for line in [l.strip[] for l in f_in] if line] * aaronasterling
* 0.06612 re.findall["\S+",f.read[]] * eyquem
* 0.06486 [ line for line in nonblank_lines[f_in] ] * aaronasterling update
0.05264 [ line for line in short_nonblank_lines[f_in] ] nonblank_lines with line[0:-1]
* 0.05451 filter[None, [line.rstrip[] for line in f_in]] * aaronasterling update 2
0.04689 [name for name in [l[0:-1] for l in f_in] if name ] aaronasterling without list[] and with line[0:-1]
0.04582 list[line for line in [l[0:-1] for l in f_in] if line] aaronasterling with line[0:-1]
0.04171 [line[0:-1] for line in f if line[0:-1] ] Felix Kling with line[0:-1]
0.03265 [name for name in f_in.read[].splitlines[] if name ] a list comprehension with read[].splitlines[]
0.03638 filter[None, [line[0:-1] for line in f_in]] aaronasterling update 2 with line[0:-1]
0.02198 filter[None, f_in.read[].splitlines[] aaronasterling update 2 with read[].splitlines[]
Nhưng vấn đề này là đặc biệt, đơn giản nhất trong tất cả: chỉ một tên trong mỗi dòng. Vì vậy, các giải pháp chỉ là các trò chơi với các dòng, phân chia và [0: -1] cắt.
Ngược lại, Regex không quan trọng với các dòng, nó đơn giản tìm thấy dữ liệu mong muốn: Tôi cho rằng đó là một cách giải quyết tự nhiên hơn, áp dụng từ các trường hợp đơn giản nhất đến các trường hợp phức tạp hơn và do đó thường được ưu tiên phương pháp điều trị văn bản.
CHỈNH SỬA
Tôi quên nói rằng tôi sử dụng Python 2.7 và tôi đã đo các thời gian trên bằng một tệp chứa 500 lần chuỗi sau đây
SMITH
JONES
WILLIAMS
TAYLOR
BROWN
DAVIES
EVANS
WILSON
THOMAS
JOHNSON
ROBERTS
ROBINSON
THOMPSON
WRIGHT
WALKER
WHITE
EDWARDS
HUGHES
GREEN
HALL
LEWIS
HARRIS
CLARKE
PATEL
JACKSON
WOOD
TURNER
MARTIN
COOPER
HILL
WARD
MORRIS
MOORE
CLARK
LEE
KING
BAKER
HARRISON
MORGAN
ALLEN
JAMES
SCOTT
PHILLIPS
WATSON
DAVIS
PARKER
PRICE
BENNETT
YOUNG
GRIFFITHS
MITCHELL
KELLY
COOK
CARTER
RICHARDSON
BAILEY
COLLINS
BELL
SHAW
MURPHY
MILLER
COX
RICHARDS
KHAN
MARSHALL
ANDERSON
SIMPSON
ELLIS
ADAMS
SINGH
BEGUM
WILKINSON
FOSTER
CHAPMAN
POWELL
WEBB
ROGERS
GRAY
MASON
ALI
HUNT
HUSSAIN
CAMPBELL
MATTHEWS
OWEN
PALMER
HOLMES
MILLS
BARNES
KNIGHT
LLOYD
BUTLER
RUSSELL
BARKER
FISHER
STEVENS
JENKINS
MURRAY
DIXON
HARVEY