Bài 3.2. Xử lý chuỗi Python: split, join

Bài 3.2. Xử lý chuỗi Python: split, join
Chào mừng các bạn trở lại với series học Python! Trong thế giới lập trình, việc thao tác với chuỗi (string) là một kỹ năng cực kỳ quan trọng. Dữ liệu văn bản có ở khắp mọi nơi: từ các tệp cấu hình, dữ liệu người dùng nhập vào, nội dung web cho đến các file log hệ thống. Python cung cấp rất nhiều phương thức mạnh mẽ để xử lý chuỗi, và trong bài này, chúng ta sẽ tập trung vào hai phương thức cực kỳ hữu ích và thường xuyên được sử dụng: split()
và join()
.
Hãy tưởng tượng bạn có một câu văn dài và muốn tách nó thành từng từ riêng biệt, hoặc bạn có một danh sách các mục và muốn ghép chúng lại thành một chuỗi duy nhất được ngăn cách bởi dấu phẩy hoặc bất kỳ ký tự nào khác. Đó chính là lúc split()
và join()
tỏa sáng!
1. Phương thức split()
: Chia nhỏ chuỗi
Phương thức split()
được dùng để chia một chuỗi thành một danh sách (list) các chuỗi con dựa trên một ký tự phân tách (delimiter) được chỉ định.
Cú pháp cơ bản
string.split(sep=None, maxsplit=-1)
Trong đó:
string
: Chuỗi gốc mà bạn muốn chia.sep
(separator - tùy chọn): Ký tự hoặc chuỗi được dùng làm điểm phân tách.- Nếu
sep
không được chỉ định hoặc làNone
,split()
sẽ mặc định chia chuỗi dựa trên khoảng trắng (whitespace) bao gồm dấu cách, tab (\t
), xuống dòng (\n
), v.v. và các chuỗi rỗng sẽ bị loại bỏ khỏi kết quả. - Nếu
sep
được chỉ định,split()
sẽ chia chuỗi tại mỗi lần xuất hiện củasep
.
- Nếu
maxsplit
(tùy chọn): Số lần tách tối đa.- Nếu là
-1
(mặc định), không có giới hạn về số lần tách. - Nếu là một số nguyên dương
n
, chuỗi sẽ được tách tối đan
lần, tạo ran+1
phần tử trong danh sách kết quả. Phần còn lại của chuỗi (sau lần tách thứn
) sẽ là phần tử cuối cùng của danh sách.
- Nếu là
Ví dụ minh họa
a. split()
không có tham số (tách theo khoảng trắng)
Đây là trường hợp sử dụng phổ biến nhất, ví dụ như tách một câu thành các từ.
sentence = " Python là ngôn ngữ lập trình phổ biến! "
words = sentence.split()
print(f"Chuỗi gốc: '{sentence}'")
print(f"Kết quả sau khi split(): {words}")
Giải thích:
sentence.split()
được gọi mà không có tham sốsep
.- Python tự động tìm các khối khoảng trắng (bao gồm cả khoảng trắng ở đầu, cuối và nhiều khoảng trắng liên tiếp giữa các từ) để tách chuỗi.
- Kết quả trả về là một danh sách các từ đã được tách ra, các khoảng trắng thừa và chuỗi rỗng đã bị loại bỏ.
Output:
Chuỗi gốc: ' Python là ngôn ngữ lập trình phổ biến! '
Kết quả sau khi split(): ['Python', 'là', 'ngôn', 'ngữ', 'lập', 'trình', 'phổ', 'biến!']
b. split()
với tham số sep
Khi dữ liệu của bạn được phân tách bằng một ký tự cụ thể (như dấu phẩy, dấu gạch nối, dấu hai chấm), bạn cần chỉ định sep
.
csv_data = "apple,banana,orange,grape"
items = csv_data.split(',') # Tách bằng dấu phẩy
print(f"Dữ liệu CSV: '{csv_data}'")
print(f"Danh sách các mục: {items}")
date_str = "20-01-2025"
date_parts = date_str.split('-') # Tách bằng dấu gạch nối
print(f"Chuỗi ngày tháng: '{date_str}'")
print(f"Các phần của ngày: {date_parts}")
Giải thích:
- Trong ví dụ đầu tiên,
split(',')
chia chuỗicsv_data
tại mỗi dấu phẩy,
. - Trong ví dụ thứ hai,
split('-')
chia chuỗidate_str
tại mỗi dấu gạch nối-
.
Output:
Dữ liệu CSV: 'apple,banana,orange,grape'
Danh sách các mục: ['apple', 'banana', 'orange', 'grape']
Chuỗi ngày tháng: '20-01-2025'
Các phần của ngày: ['20', '01', '2025']
Lưu ý quan trọng: Nếu bạn chỉ định sep
, các chuỗi rỗng có thể xuất hiện trong kết quả nếu có hai dấu phân tách liền nhau hoặc dấu phân tách ở đầu/cuối chuỗi.
data = "a,,b,c,"
parts = data.split(',')
print(f"Chuỗi gốc: '{data}'")
print(f"Kết quả split(','): {parts}")
Output:
Chuỗi gốc: 'a,,b,c,'
Kết quả split(','): ['a', '', 'b', 'c', '']
c. split()
với tham số maxsplit
Tham số này hữu ích khi bạn chỉ muốn tách một phần đầu của chuỗi.
log_entry = "INFO:user_logged_in:id=123:ip=192.168.1.1"
# Chỉ tách lần đầu tiên tại dấu ':'
log_parts_1 = log_entry.split(':', maxsplit=1)
print(f"Tách 1 lần: {log_parts_1}")
# Tách 2 lần tại dấu ':'
log_parts_2 = log_entry.split(':', maxsplit=2)
print(f"Tách 2 lần: {log_parts_2}")
# Tách không giới hạn (mặc định)
log_parts_all = log_entry.split(':')
print(f"Tách tất cả: {log_parts_all}")
Giải thích:
maxsplit=1
: Tách chuỗi tại dấu:
đầu tiên. Kết quả có 2 phần tử: phần trước dấu:
đầu tiên và phần còn lại của chuỗi.maxsplit=2
: Tách chuỗi tại 2 dấu:
đầu tiên. Kết quả có 3 phần tử.- Không có
maxsplit
(hoặcmaxsplit=-1
): Tách tại tất cả các dấu:
.
Output:
Tách 1 lần: ['INFO', 'user_logged_in:id=123:ip=192.168.1.1']
Tách 2 lần: ['INFO', 'user_logged_in', 'id=123:ip=192.168.1.1']
Tách tất cả: ['INFO', 'user_logged_in', 'id=123', 'ip=192.168.1.1']
2. Phương thức join()
: Ghép nối các phần tử
Phương thức join()
thực hiện công việc ngược lại với split()
. Nó lấy một iterable (như list, tuple) chứa các chuỗi và ghép nối chúng lại thành một chuỗi duy nhất, sử dụng chuỗi mà phương thức join()
được gọi làm ký tự nối (separator).
Cú pháp cơ bản
separator.join(iterable)
Trong đó:
separator
: Là chuỗi sẽ được chèn vào giữa các phần tử củaiterable
trong chuỗi kết quả.iterable
: Một đối tượng có thể lặp qua (như list, tuple, set) mà tất cả các phần tử của nó phải là chuỗi (string). Nếu có bất kỳ phần tử nào không phải là chuỗi, bạn sẽ gặp lỗiTypeError
.
Điểm cần nhấn mạnh: join()
là một phương thức của chuỗi (separator
), không phải là phương thức của list
hay tuple
. Đây là điểm nhiều người mới học hay nhầm lẫn. Bạn gọi join()
trên chuỗi sẽ đóng vai trò làm dấu nối.
Ví dụ minh họa
a. Ghép nối danh sách các từ thành câu
word_list = ['Học', 'Python', 'thật', 'thú', 'vị']
# Dùng dấu cách làm ký tự nối
sentence = ' '.join(word_list)
print(f"Danh sách từ: {word_list}")
print(f"Câu ghép lại: '{sentence}'")
# Dùng dấu gạch nối làm ký tự nối
hyphenated = '-'.join(word_list)
print(f"Chuỗi nối bằng gạch nối: '{hyphenated}'")
# Ghép nối không có ký tự nối (chuỗi rỗng)
combined = ''.join(word_list)
print(f"Chuỗi ghép liền: '{combined}'")
Giải thích:
' '.join(word_list)
: Lấy chuỗi dấu cách' '
làmตัวคั่น và chèn nó vào giữa mỗi phần tử củaword_list
.'-'.join(word_list)
: Lấy chuỗi gạch nối'-'
làmตัวคั่น.''.join(word_list)
: Lấy chuỗi rỗng''
làmตัวคั่น, kết quả là các từ được ghép liền nhau.
Output:
Danh sách từ: ['Học', 'Python', 'thật', 'thú', 'vị']
Câu ghép lại: 'Học Python thật thú vị'
Chuỗi nối bằng gạch nối: 'Học-Python-thật-thú-vị'
Chuỗi ghép liền: 'HọcPythonthậtthúvị'
b. Ghép nối danh sách chứa các kiểu dữ liệu khác (Cần chuyển đổi!)
Như đã đề cập, join()
yêu cầu tất cả các phần tử trong iterable phải là chuỗi. Nếu bạn có một danh sách chứa số hoặc các kiểu dữ liệu khác, bạn cần chuyển đổi chúng thành chuỗi trước.
mixed_list = ['Sản phẩm', 101, 'Giá', 25.5, True]
# Cố gắng join trực tiếp sẽ gây lỗi TypeError
# result = ', '.join(mixed_list) # --> TypeError: sequence item 1: expected str instance, int found
# Cách sửa: Chuyển đổi tất cả phần tử thành chuỗi trước khi join
# Sử dụng list comprehension để chuyển đổi
string_list = [str(item) for item in mixed_list]
print(f"Danh sách sau khi chuyển đổi: {string_list}")
result = ', '.join(string_list)
print(f"Chuỗi kết quả: '{result}'")
Giải thích:
- Dòng bị comment
# result = ', '.join(mixed_list)
sẽ gây lỗi vìmixed_list
chứa số nguyên (101
), số thực (25.5
) và boolean (True
), không phải tất cả đều là chuỗi. [str(item) for item in mixed_list]
là một list comprehension. Nó tạo ra một danh sách mới (string_list
) bằng cách lặp qua từngitem
trongmixed_list
và áp dụng hàmstr()
để chuyển đổiitem
đó thành chuỗi.- Sau khi có
string_list
chỉ chứa các chuỗi,', '.join(string_list)
hoạt động thành công.
Output:
Danh sách sau khi chuyển đổi: ['Sản phẩm', '101', 'Giá', '25.5', 'True']
Chuỗi kết quả: 'Sản phẩm, 101, Giá, 25.5, True'
c. Ghép nối các phần tử của một tuple
join()
hoạt động với bất kỳ iterable nào, không chỉ list.
my_tuple = ('red', 'green', 'blue')
color_string = ' | '.join(my_tuple)
print(f"Tuple gốc: {my_tuple}")
print(f"Chuỗi màu sắc: '{color_string}'")
Output:
Tuple gốc: ('red', 'green', 'blue')
Chuỗi màu sắc: 'red | green | blue'
3. Kết hợp split()
và join()
Sức mạnh thực sự thường đến từ việc kết hợp các công cụ này. Bạn có thể dùng split()
để phân tách dữ liệu, xử lý các phần tử, rồi dùng join()
để ghép chúng lại theo một định dạng mới.
Ví dụ: Chuyển đổi định dạng ngày tháng từ YYYY-MM-DD
sang DD/MM/YYYY
.
date_iso = "2025-01-20"
# 1. Tách chuỗi theo dấu '-'
parts = date_iso.split('-') # ['2025', '01', '20']
print(f"Các phần đã tách: {parts}")
# 2. Đảo ngược thứ tự các phần tử (năm, tháng, ngày -> ngày, tháng, năm)
# Có thể dùng slicing: parts[::-1] hoặc list.reverse()
reversed_parts = parts[::-1] # ['20', '01', '2025']
# Hoặc:
# parts.reverse()
# reversed_parts = parts
print(f"Các phần sau khi đảo ngược: {reversed_parts}")
# 3. Ghép nối lại bằng dấu '/'
date_dmy = '/'.join(reversed_parts)
print(f"Định dạng ngày mới: {date_dmy}")
Giải thích:
split('-')
tách chuỗi ngày theo chuẩn ISO thành danh sách['2025', '01', '20']
.parts[::-1]
là một kỹ thuật slicing trong Python để tạo ra một bản sao đảo ngược của danh sáchparts
.'/'.join(reversed_parts)
dùng dấu/
để nối các phần tử đã đảo ngược lại thành chuỗi20/01/2025
.
Output:
Các phần đã tách: ['2025', '01', '20']
Các phần sau khi đảo ngược: ['20', '01', '2025']
Định dạng ngày mới: 20/01/2025
split()
và join()
là hai phương thức cực kỳ linh hoạt và mạnh mẽ trong bộ công cụ xử lý chuỗi của Python. Hiểu rõ cách chúng hoạt động và khi nào nên sử dụng chúng sẽ giúp bạn xử lý dữ liệu văn bản một cách hiệu quả và dễ dàng hơn rất nhiều. Hãy thực hành với nhiều ví dụ khác nhau để làm chủ chúng nhé!
Comments