Câu hỏi: Tôi đang sử dụng split ('\ n') để nhận các dòng trong một chuỗi và thấy rằng '' .split () trả về danh sách trống [], trong khi '' .split ('\ n') trả về [''] .
Phương thức str.split () có hai thuật toán. Nếu không có đối số nào được đưa ra, nó sẽ phân tách trên các khoảng trắng lặp đi lặp lại. Tuy nhiên, nếu một đối số được đưa ra, nó được coi là một dấu phân cách duy nhất không có lần chạy lặp lại.
Trong trường hợp tách một chuỗi rỗng, chế độ đầu tiên (không có đối số) sẽ trả về một danh sách trống vì khoảng trắng được ăn và không có giá trị nào được đưa vào danh sách kết quả.
Ngược lại, chế độ thứ hai (với một đối số như \n
) sẽ tạo ra trường trống đầu tiên. Hãy xem xét nếu bạn đã viết '\n'.split('\n')
, bạn sẽ nhận được hai trường (một phần tách, cho bạn hai nửa).
Câu hỏi: Có bất kỳ lý do cụ thể cho sự khác biệt như vậy?
Chế độ đầu tiên này hữu ích khi dữ liệu được căn chỉnh trong các cột với số lượng khoảng trắng khác nhau. Ví dụ:
>>> data = '''\
Shasta California 14,200
McKinley Alaska 20,300
Fuji Japan 12,400
'''
>>> for line in data.splitlines():
print line.split()
['Shasta', 'California', '14,200']
['McKinley', 'Alaska', '20,300']
['Fuji', 'Japan', '12,400']
Chế độ thứ hai hữu ích cho dữ liệu được phân tách, chẳng hạn như CSV trong đó dấu phẩy lặp lại biểu thị các trường trống. Ví dụ:
>>> data = '''\
Guido,BDFL,,Amsterdam
Barry,FLUFL,,USA
Tim,,,USA
'''
>>> for line in data.splitlines():
print line.split(',')
['Guido', 'BDFL', '', 'Amsterdam']
['Barry', 'FLUFL', '', 'USA']
['Tim', '', '', 'USA']
Lưu ý, số lượng trường kết quả là một lớn hơn số lượng dấu phân cách. Hãy nghĩ đến việc cắt một sợi dây. Nếu bạn không cắt giảm, bạn có một mảnh. Làm một vết cắt, cho hai mảnh. Làm hai vết cắt, cho ba mảnh. Và đó là phương thức str.split (delimiter) của Python :
>>> ''.split(',') # No cuts
['']
>>> ','.split(',') # One cut
['', '']
>>> ',,'.split(',') # Two cuts
['', '', '']
Câu hỏi: Và có cách nào thuận tiện hơn để đếm các dòng trong một chuỗi không?
Vâng, có một vài cách dễ dàng. Một cái sử dụng str.count () và cái kia sử dụng str.splitlines () . Cả hai cách sẽ cho cùng một câu trả lời trừ khi dòng cuối cùng bị thiếu \n
. Nếu dòng mới cuối cùng bị thiếu, phương pháp str.splitlines sẽ đưa ra câu trả lời chính xác. Một kỹ thuật nhanh hơn cũng chính xác sử dụng phương pháp đếm nhưng sau đó sửa nó cho dòng mới cuối cùng:
>>> data = '''\
Line 1
Line 2
Line 3
Line 4'''
>>> data.count('\n') # Inaccurate
3
>>> len(data.splitlines()) # Accurate, but slow
4
>>> data.count('\n') + (not data.endswith('\n')) # Accurate and fast
4
Câu hỏi từ @Kaz: Tại sao quái vật là hai thuật toán rất khác nhau được cắm vào một chức năng duy nhất?
Chữ ký cho str.split khoảng 20 năm và một số API từ thời đó là hoàn toàn thực dụng. Mặc dù không hoàn hảo, chữ ký phương thức cũng không "khủng". Đối với hầu hết các phần, các lựa chọn thiết kế API của Guido đã vượt qua thử thách của thời gian.
API hiện tại không phải là không có lợi thế. Hãy xem xét các chuỗi như:
ps_aux_header = "USER PID %CPU %MEM VSZ"
patient_header = "name,age,height,weight"
Khi được yêu cầu chia các chuỗi này thành các trường, mọi người có xu hướng mô tả cả hai bằng cách sử dụng cùng một từ tiếng Anh, "split". Khi được yêu cầu đọc mã như fields = line.split()
hoặc fields = line.split(',')
, người ta có xu hướng để giải thích một cách chính xác những điều khoản là "chia tách một dòng vào các lĩnh vực".
Công cụ chuyển văn bản thành cột của Microsoft Excel đã đưa ra lựa chọn API tương tự và kết hợp cả hai thuật toán phân tách trong cùng một công cụ. Mọi người dường như mô hình hóa phân tách trường như một khái niệm duy nhất mặc dù có nhiều hơn một thuật toán có liên quan.