Xử Lý Chuỗi Và Cấu Trúc Dữ Liệu Trong Python

Cơ Bản Về Chuỗi Ký Tự

Trong khi các hệ thống máy tính sơ khai chủ yếu phục vụ cho tính toán số học thuần túy, nhu cầu lưu trữ và xử lý văn bản đã trở thành yêu cầu cốt lõi của phần mềm hiện đại. Python xử lý văn bản thông qua kiểu chuỗi (string), được định nghĩa là một dãy các ký tự được bao bọc bởi dấu nháy đơn hoặc kép. Chuỗi hỗ trợ đa dạng phương thức xử lý từ định dạng, cắt chuỗi, đến kiểm tra ký tự.

def thao_tac_chuoi():
    van_ban = "python programming language"
    
    # Kiểm tra độ dài và định dạng
    print(f"Độ dài: {len(van_ban)}")
    print(f"Viết hoa chữ đầu: {van_ban.title()}")
    print(f"Toàn bộ chữ hoa: {van_ban.upper()}")
    
    # Định vị và kiểm tra
    print(f"Vị trí 'gram': {van_ban.find('gram')}")
    print(f"Bắt đầu bằng 'pyth': {van_ban.startswith('pyth')}")
    print(f"Kết thúc bằng 'age': {van_ban.endswith('age')}")
    
    # Căn chỉnh và loại bỏ khoảng trắng
    print(f"Căn giữa: {van_ban.center(40, '=')}")
    du_lieu_nhieu = "   dữ liệu cần làm sạch   "
    print(f"Đã loại bỏ khoảng trắng: '{du_lieu_nhieu.strip()}'")
    
    # Cắt chuỗi và kiểm tra loại ký tự
    ma_hoa = "id8842v"
    print(f"Cắt từ index 2 đến 5: {ma_hoa[2:5]}")
    print(f"Là số không? {ma_hoa.isdigit()}")
    print(f"Chứa chữ và số? {ma_hoa.isalnum()}")

if __name__ == "__main__":
    thao_tac_chuoi()

Danh Sách (List)

List là cấu trúc mảng động, cho phép lưu trữ dữ liệu hỗn hợp và hỗ trợ thao tác thêm, xóa, chèn trực tiếp.

def quan_ly_danh_sach():
    so_nguyen = [10, 25, 30, 45, 50]
    print(f"Ban đầu: {so_nguyen}")
    
    # Mở rộng và sao chép
    danh_sach_nhan = ["x"] * 3
    print(danh_sach_nhan)
    print(f"Số phần tử: {len(so_nguyen)}")
    
    # Truy cập và sửa đổi
    print(f"Phần tử cuối: {so_nguyen[-1]}")
    so_nguyen[2] = 99
    so_nguyen.append(110)
    so_nguyen.insert(0, 5)
    so_nguyen.extend([200, 300])
    print(f"Sau khi mở rộng: {so_nguyen}")
    
    # Xóa phần tử
    try:
        so_nguyen.remove(99)
    except ValueError:
        pass
    del so_nguyen[0]
    so_nguyen.clear()
    print(f"Danh sách trống: {so_nguyen}")

if __name__ == "__main__":
    quan_ly_danh_sach()

Việc trích xuất dữ liệu từ list được thực hiện qua cú pháp slicing, hỗ trợ sao chép nông và đảo ngược mảng nhanh chóng.

def cat_va_sap_xep():
    trai_cay = ["táo", "nho", "dâu", "cam", "xoài"]
    
    # Slicing cơ bản
    subset = trai_cay[1:4]
    ban_sao = trai_cay[:]
    dao_nguoc = trai_cay[::-1]
    print(f"Trích xuất: {subset}")
    print(f"Đảo chiều: {dao_nguoc}")
    
    # Sắp xếp dữ liệu
    tu_vung = ["zebra", "apple", "python", "rust"]
    tang_dan = sorted(tu_vung)
    theo_do_dai = sorted(tu_vung, key=len)
    tu_vung.sort(reverse=True)
    print(f"Sắp xếp tăng: {tang_dan}")
    print(f"Ưu tiên độ dài: {theo_do_dai}")
    print(f"Giảm dần tại chỗ: {tu_vung}")

if __name__ == "__main__":
    cat_va_sap_xep()

Python cung cấp cú pháp List Comprehension để khởi tạo danh sách gọn gàng. Khi xử lý dữ liệu cực lớn, nên sử dụng Generator Expression để tiết kiệm bộ nhớ RAM, vì nó chỉ tính toán giá trị khi được yêu cầu (lazy evaluation).

import sys

def kiem_tra_bo_nho():
    list_goc = [n ** 3 for n in range(1, 1000)]
    gen_goc = (n ** 3 for n in range(1, 1000))
    
    print(f"List tốn: {sys.getsizeof(list_goc)} bytes")
    print(f"Generator tốn: {sys.getsizeof(gen_goc)} bytes")

def tao_day_so(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

def main_optimization():
    kiem_tra_bo_nho()
    print("10 số đầu dãy Fibonacci:")
    for gia_tri in tao_day_so(10):
        print(gia_tri, end=" ")
    print()

if __name__ == "__main__":
    main_optimization()

Bộ Giá Trị (Tuple)

Tuple hoạt động tương tự List nhưng có tính chất bất biến (immutable). Một khi đã khởi tạo, phần tử bên trong không thể bị thay thế hay xóa bỏ.

def xu_ly_tuple():
    thong_tin = ("Trần Minh", 28, True, "Hà Nội")
    print(f"Dữ liệu gốc: {thong_tin}")
    print(f"Tên: {thong_tin[0]}")
    
    # Duyệt phần tử
    for item in thong_tin:
        print(item)
        
    # Tuple mới gán lại tham chiếu
    thong_tin = ("Lê Hoa", 24, False, "Đà Nẵng")
    
    # Chuyển đổi sang list để chỉnh sửa
    tmp = list(thong_tin)
    tmp[1] = 25
    print(f"Tuple sau sửa đổi: {tuple(tmp)}")

if __name__ == "__main__":
    xu_ly_tuple()

Việc ưu tiên sử dụng Tuple thay vì List mang lại ba lợi ích chính: tính an toàn dữ liệu nhờ cơ chế bất biến, tối ưu hóa bộ nhớ vật lý, và tốc độ truy xuất nhanh hơn. Ngoài ra, Tuple đảm bảo an toàn luồng (thread-safe) trong các ứng dụng đa tiến trình.

Tập Hợp (Set)

Set lưu trữ các phần tử duy nhất và hỗ trợ đầy đủ các phép toán toán học như giao, hợp, hiệu.

def thao_tac_tap_hop():
    nhom_a = {1, 2, 3, 3, 4}
    nhom_b = set(range(3, 8))
    
    print(f"Phần tử duy nhất A: {nhom_a}")
    nhom_a.add(5)
    nhom_b.update([10, 11])
    
    # Xóa an toàn không gây lỗi nếu khóa không tồn tại
    nhom_b.discard(10)
    
    # Toán tử tập hợp
    print(f"Giao (∩): {nhom_a & nhom_b}")
    print(f"Hợp (∪): {nhom_a | nhom_b}")
    print(f"Hiệu (A-B): {nhom_a - nhom_b}")
    print(f"Đối xứng (⊕): {nhom_a ^ nhom_b}")
    
    # Kiểm tra quan hệ tập hợp
    print(f"B là tập con của A? {nhom_b <= nhom_a}")

if __name__ == "__main__":
    thao_tac_tap_hop()

Từ Điển (Dictionary)

Dictionary lưu trữ dữ liệu theo cặp khóa-giá trị (key-value), cho phép truy xuất cực nhanh thông qua ánh xạ băm.

def quan_ly_du_lieu():
    bang_diem = {"Nguyen Van A": 85, "Tran Thi B": 92, "Le Van C": 78}
    
    print(f"Điểm của A: {bang_diem['Nguyen Van A']}")
    for khoa in bang_diem:
        print(f"{khoa} -> {bang_diem[khoa]}")
        
    # Cập nhật và chèn mới
    bang_diem["Tran Thi B"] = 95
    bang_diem["Hoang Van D"] = 88
    bang_diem.update(Pham Thi E=90, Do Van F=75)
    
    # Lấy giá trị an toàn với mặc định
    print(f"Điểm G (mặc định 0): {bang_diem.get('G', 0)}")
    print(f"Xóa cuối: {bang_diem.popitem()}")
    print(f"Xóa theo khóa: {bang_diem.pop('Le Van C', -1)}")
    
    bang_diem.clear()
    print(f"Đã xóa sạch: {bang_diem}")

if __name__ == "__main__":
    quan_ly_du_lieu()

Bài Tập Thực Hành

Hiệu Ứng Chữ Chạy

import os
import time
import sys

def chay_chu(noi_dung="Chào mừng đến với Python"):
    while True:
        os.system('cls' if os.name == 'nt' else 'clear')
        print(noi_dung)
        time.sleep(0.2)
        noi_dung = noi_dung[1:] + noi_dung[0]

if __name__ == "__main__":
    chay_chu()

Tạo Mã Xác Thực Ngẫu Nhiên

import string
import random

def sinh_ma_xac_thuc(kich_thuoc=6):
    ky_tu_hop_le = string.ascii_letters + string.digits
    return ''.join(random.choices(ky_tu_hop_le, k=kich_thuoc))

print(sinh_ma_xac_thuc())

Tách Phần Mở Rộng File

def lay_phan_mo_rong(ten_file, bao_gom_dau_cham=False):
    vi_tri = ten_file.rfind('.')
    if 0 < vi_tri < len(ten_file) - 1:
        bat_dau = vi_tri if bao_gom_dau_cham else vi_tri + 1
        return ten_file[bat_dau:]
    return ""

print(lay_phan_mo_rong("baocao.docx", True))

Tìm Hai Giá Trị Lớn Nhất Trong Mảng

def tim_hai_gia_tri_lon_nhat(mang):
    if len(mang) < 2:
        raise ValueError("Mảng cần ít nhất 2 phần tử")
        
    lon_nhat, lon_thu_hai = sorted(mang[:2], reverse=True)
    
    for phan_tu in mang[2:]:
        if phan_tu > lon_nhat:
            lon_thu_hai = lon_nhat
            lon_nhat = phan_tu
        elif lon_thu_hai < phan_tu:
            lon_thu_hai = phan_tu
            
    return lon_nhat, lon_thu_hai

print(tim_hai_gia_tri_lon_nhat([5, 8, 2, 9, 4]))

Tính Số Ngày Trong Năm

def kiem_tra_nam_nhuan(nam):
    return nam % 4 == 0 and (nam % 100 != 0 or nam % 400 == 0)

def tinh_ngay_thu(nam, thang, ngay):
    ngay_trong_thang = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    if kiem_tra_nam_nhuan(nam):
        ngay_trong_thang[1] = 29
        
    tong_ngay = sum(ngay_trong_thang[:thang-1]) + ngay
    return tong_ngay

print(tinh_ngay_thu(2024, 3, 1))

Tam Giác Pascal

def ve_tam_giac_pascal(so_dong):
    tam_giac = []
    for row in range(so_dong):
        dong_hien_tai = [1] * (row + 1)
        for col in range(1, row):
            dong_hien_tai[col] = tam_giac[row-1][col-1] + tam_giac[row-1][col]
        tam_giac.append(dong_hien_tai)
        
        for val in dong_hien_tai:
            print(f"{val}\t", end="")
        print()

ve_tam_giac_pascal(5)

Ứng Dụng Tổng Hợp

Chọn Số Xổ Số

from random import sample, randint

def hien_thi_ve(balls):
    ket_qua = " ".join(f"{b:02d}" for b in balls[:6]) + " | " + f"{balls[6]:02d}"
    print(ket_qua)

def chon_so():
    do_thuong = sample(range(1, 34), 6)
    do_thuong.sort()
    do_thuong.append(randint(1, 16))
    return do_thuong

for _ in range(3):
    hien_thi_ve(chon_so())

Bài Toán Vòng Tròn Josephus

def giai_quyet_josephus(tong_nguoi, buoc_nhay, so_nguoi_tha):
    trang_thai = [True] * tong_nguoi
    dem, vi_tri, bo_dem = 0, 0, 0
    
    while dem < so_nguoi_tha:
        if trang_thai[vi_tri]:
            bo_dem += 1
            if bo_dem == buoc_nhay:
                trang_thai[vi_tri] = False
                dem += 1
                bo_dem = 0
        vi_tri = (vi_tri + 1) % tong_nguoi
        
    return [i + 1 for i, con_song in enumerate(trang_thai) if con_song]

print(f"Vị trí sống sót: {giai_quyet_josephus(30, 9, 15)}")

Game Caro Đơn Giản (Dùng Dict)

def hien_thi_ban_co(ban_co):
    layout = f"{ban_co['TL']}|{ban_co['TM']}|{ban_co['TR']}\n-+-+-\n{ban_co['ML']}|{ban_co['MM']}|{ban_co['MR']}\n-+-+-\n{ban_co['BL']}|{ban_co['BM']}|{ban_co['BR']}"
    print(layout)

def choi_caro():
    ban_co_goc = {k: ' ' for k in ['TL', 'TM', 'TR', 'ML', 'MM', 'MR', 'BL', 'BM', 'BR']}
    
    while True:
        hien_thi = ban_co_goc.copy()
        luot_diem = 'X'
        buoc_diem = 0
        
        while buoc_diem < 9:
            os.system('cls' if os.name == 'nt' else 'clear')
            hien_thi_ban_co(hien_thi)
            dia_chi = input(f"Lượt {luot_diem}, chọn ô: ")
            
            if hien_thi[dia_chi] == ' ':
                hien_thi[dia_chi] = luot_diem
                buoc_diem += 1
                luot_diem = 'O' if luot_diem == 'X' else 'X'
                
        if input("Chơi lại? (y/n): ").lower() != 'y':
            break

# choi_caro()

Thẻ: python chuỗi-ký-tự danh-sach tap-hop tu-dien

Đăng vào ngày 4 tháng 10 lúc 10:37