Bài 5: Lists - Danh Sách (Phần 1)
Mục Tiêu Bài Học
Sau khi hoàn thành bài này, bạn sẽ:
- ✅ Hiểu list là gì và khi nào dùng list
- ✅ Tạo và truy cập phần tử trong list
- ✅ Sử dụng indexing và slicing với list
- ✅ Thêm, xóa, sửa phần tử trong list
- ✅ Sử dụng list methods cơ bản
List Là Gì?
List là một collection có thứ tự, có thể thay đổi (mutable), và cho phép các phần tử trùng lặp.
# List với các kiểu dữ liệu khác nhaunumbers = [1, 2, 3, 4, 5]names = ["Alice", "Bob", "Charlie"]mixed = [1, "Hello", 3.14, True, [1, 2, 3]]empty = [] print(type(numbers)) # <class 'list'>
So sánh List vs String:
# String - immutable (không đổi)text = "Hello"# text[0] = "h" # TypeError! Không thể thay đổi # List - mutable (có thể đổi)items = ["H", "e", "l", "l", "o"]items[0] = "h" # ✅ OKprint(items) # ['h', 'e', 'l', 'l', 'o']
Tạo List
Cách 1: List Literals
# Empty listempty_list = [] # List với phần tửfruits = ["apple", "banana", "orange"]numbers = [1, 2, 3, 4, 5] # Multi-line listshopping = [ "milk", "eggs", "bread", "butter"] # Mixed typesmixed = [1, "two", 3.0, True, None]
Cách 2: list() Constructor
# Từ stringchars = list("Python")print(chars) # ['P', 'y', 't', 'h', 'o', 'n'] # Từ tupletuple_data = (1, 2, 3)list_data = list(tuple_data)print(list_data) # [1, 2, 3] # Từ rangenumbers = list(range(5))print(numbers) # [0, 1, 2, 3, 4] numbers2 = list(range(1, 10, 2))print(numbers2) # [1, 3, 5, 7, 9]
Cách 3: List Comprehension (nhanh)
# Tạo list từ rangesquares = [x**2 for x in range(5)]print(squares) # [0, 1, 4, 9, 16] # Với điều kiệnevens = [x for x in range(10) if x % 2 == 0]print(evens) # [0, 2, 4, 6, 8] # Sẽ học chi tiết ở bài sau
Truy Cập Phần Tử - Indexing
fruits = ["apple", "banana", "orange", "mango", "grape"]# 0 1 2 3 4 (positive)# -5 -4 -3 -2 -1 (negative) # Positive indexingprint(fruits[0]) # appleprint(fruits[2]) # orange # Negative indexingprint(fruits[-1]) # grape (cuối)print(fruits[-2]) # mango # Access nested listmatrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]print(matrix[0]) # [1, 2, 3]print(matrix[0][0]) # 1print(matrix[1][2]) # 6
Lỗi phổ biến:
fruits = ["apple", "banana"]# print(fruits[5]) # IndexError: list index out of range # Cách an toànindex = 5if index < len(fruits): print(fruits[index])else: print("Index out of range")
Slicing - Cắt List
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # [start:stop]print(numbers[2:5]) # [2, 3, 4]print(numbers[:5]) # [0, 1, 2, 3, 4] (từ đầu)print(numbers[5:]) # [5, 6, 7, 8, 9] (đến cuối)print(numbers[:]) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] (copy) # [start:stop:step]print(numbers[::2]) # [0, 2, 4, 6, 8] (mỗi 2)print(numbers[1::2]) # [1, 3, 5, 7, 9] (lẻ)print(numbers[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] (đảo) # Negative indicesprint(numbers[-5:]) # [5, 6, 7, 8, 9]print(numbers[:-5]) # [0, 1, 2, 3, 4]
Ứng dụng:
# Lấy 3 phần tử đầutop_3 = ["Gold", "Silver", "Bronze", "4th", "5th"]print(top_3[:3]) # ['Gold', 'Silver', 'Bronze'] # Lấy 3 phần tử cuốiscores = [85, 90, 78, 92, 88]last_3 = scores[-3:]print(last_3) # [78, 92, 88] # Copy listoriginal = [1, 2, 3]copy = original[:] # Tạo copy mớicopy[0] = 999print(original) # [1, 2, 3] (không đổi)print(copy) # [999, 2, 3]
Thay Đổi Phần Tử
Thay đổi một phần tử
fruits = ["apple", "banana", "orange"] # Thay đổi theo indexfruits[1] = "mango"print(fruits) # ['apple', 'mango', 'orange'] # Thay đổi phần tử cuốifruits[-1] = "grape"print(fruits) # ['apple', 'mango', 'grape']
Thay đổi nhiều phần tử
numbers = [1, 2, 3, 4, 5] # Thay slicenumbers[1:3] = [20, 30]print(numbers) # [1, 20, 30, 4, 5] # Thay bằng nhiều phần tử hơnnumbers[1:3] = [10, 20, 30, 40]print(numbers) # [1, 10, 20, 30, 40, 4, 5] # Xóa bằng cách gán empty listnumbers[2:4] = []print(numbers) # [1, 10, 40, 4, 5]
Thêm Phần Tử - Adding
1. append() - Thêm vào cuối
fruits = ["apple", "banana"] # Thêm một phần tửfruits.append("orange")print(fruits) # ['apple', 'banana', 'orange'] # Thêm list (như một phần tử)fruits.append(["mango", "grape"])print(fruits) # ['apple', 'banana', 'orange', ['mango', 'grape']]
2. extend() - Thêm nhiều phần tử
fruits = ["apple", "banana"] # Extend với listfruits.extend(["orange", "mango"])print(fruits) # ['apple', 'banana', 'orange', 'mango'] # Extend với string (từng ký tự)fruits.extend("XY")print(fruits) # ['apple', 'banana', 'orange', 'mango', 'X', 'Y'] # So sánh append vs extendlist1 = [1, 2]list1.append([3, 4])print(list1) # [1, 2, [3, 4]] list2 = [1, 2]list2.extend([3, 4])print(list2) # [1, 2, 3, 4]
3. insert() - Thêm vào vị trí
fruits = ["apple", "banana", "orange"] # Insert tại index 1fruits.insert(1, "mango")print(fruits) # ['apple', 'mango', 'banana', 'orange'] # Insert ở đầufruits.insert(0, "grape")print(fruits) # ['grape', 'apple', 'mango', 'banana', 'orange'] # Insert ở cuối (dùng append tốt hơn)fruits.insert(len(fruits), "kiwi")print(fruits)
4. Toán tử +
list1 = [1, 2, 3]list2 = [4, 5, 6] # Nối list (tạo list mới)result = list1 + list2print(result) # [1, 2, 3, 4, 5, 6]print(list1) # [1, 2, 3] (không đổi) # += (thay đổi list gốc)list1 += list2print(list1) # [1, 2, 3, 4, 5, 6]
Xóa Phần Tử - Removing
1. remove() - Xóa theo giá trị
fruits = ["apple", "banana", "orange", "banana"] # Xóa phần tử đầu tiên tìm thấyfruits.remove("banana")print(fruits) # ['apple', 'orange', 'banana'] # Lỗi nếu không tìm thấy# fruits.remove("grape") # ValueError! # Cách an toànif "grape" in fruits: fruits.remove("grape")
2. pop() - Xóa theo index
fruits = ["apple", "banana", "orange"] # Pop cuối (default)last = fruits.pop()print(last) # orangeprint(fruits) # ['apple', 'banana'] # Pop tại indexfirst = fruits.pop(0)print(first) # appleprint(fruits) # ['banana'] # Lỗi nếu index không hợp lệ# fruits.pop(10) # IndexError!
3. del - Xóa theo index hoặc slice
numbers = [1, 2, 3, 4, 5] # Xóa tại indexdel numbers[2]print(numbers) # [1, 2, 4, 5] # Xóa slicedel numbers[1:3]print(numbers) # [1, 5] # Xóa toàn bộ list# del numbers# print(numbers) # NameError!
4. clear() - Xóa tất cả
fruits = ["apple", "banana", "orange"] fruits.clear()print(fruits) # []print(len(fruits)) # 0
So sánh:
# remove() - xóa theo giá trịitems = ["a", "b", "c"]items.remove("b") # ['a', 'c'] # pop() - xóa theo index, trả về giá trịitems = ["a", "b", "c"]value = items.pop(1) # value = "b", items = ['a', 'c'] # del - xóa theo index, không trả vềitems = ["a", "b", "c"]del items[1] # items = ['a', 'c'] # clear() - xóa tất cảitems = ["a", "b", "c"]items.clear() # items = []
List Methods Khác
1. index() - Tìm vị trí
fruits = ["apple", "banana", "orange", "banana"] # Tìm index đầu tiênpos = fruits.index("banana")print(pos) # 1 # Tìm từ vị trí cụ thểpos2 = fruits.index("banana", 2) # Tìm từ index 2print(pos2) # 3 # Lỗi nếu không tìm thấy# fruits.index("grape") # ValueError! # Cách an toànif "grape" in fruits: pos = fruits.index("grape")else: print("Not found")
2. count() - Đếm số lần xuất hiện
numbers = [1, 2, 2, 3, 2, 4, 2, 5] count = numbers.count(2)print(count) # 4 # Đếm stringwords = ["hello", "world", "hello", "python"]print(words.count("hello")) # 2
3. sort() - Sắp xếp
# Sort tăng dầnnumbers = [3, 1, 4, 1, 5, 9, 2]numbers.sort()print(numbers) # [1, 1, 2, 3, 4, 5, 9] # Sort giảm dầnnumbers.sort(reverse=True)print(numbers) # [9, 5, 4, 3, 2, 1, 1] # Sort stringsfruits = ["orange", "apple", "banana"]fruits.sort()print(fruits) # ['apple', 'banana', 'orange'] # Sort theo lengthwords = ["python", "is", "awesome"]words.sort(key=len)print(words) # ['is', 'python', 'awesome']
4. reverse() - Đảo ngược
numbers = [1, 2, 3, 4, 5] numbers.reverse()print(numbers) # [5, 4, 3, 2, 1] # Hoặc dùng slicingnumbers2 = [1, 2, 3, 4, 5]reversed_list = numbers2[::-1]print(reversed_list) # [5, 4, 3, 2, 1]
5. copy() - Sao chép
original = [1, 2, 3] # Shallow copy với copy()copy1 = original.copy()copy1[0] = 999print(original) # [1, 2, 3] (không đổi)print(copy1) # [999, 2, 3] # Copy với slicingcopy2 = original[:] # Copy với list()copy3 = list(original) # Reference (KHÔNG phải copy!)ref = originalref[0] = 999print(original) # [999, 2, 3] (đã đổi!)
Ví Dụ Thực Tế
1. To-Do List Manager
# To-do listtodos = [] # Thêm tasktodos.append("Buy groceries")todos.append("Finish homework")todos.append("Call mom") print("To-Do List:")for i, task in enumerate(todos, 1): print(f"{i}. {task}") # Hoàn thành taskcompleted = todos.pop(1) # Xóa "Finish homework"print(f"\nCompleted: {completed}") # Thêm task mớitodos.insert(0, "Wake up early") # Ưu tiên cao print("\nUpdated To-Do List:")for i, task in enumerate(todos, 1): print(f"{i}. {task}")
2. Shopping Cart
# Shopping cartcart = [] # Thêm itemscart.append({"name": "Apple", "price": 2.5, "qty": 3})cart.append({"name": "Banana", "price": 1.5, "qty": 5})cart.append({"name": "Orange", "price": 3.0, "qty": 2}) # Display cartprint("Shopping Cart:")total = 0for item in cart: subtotal = item["price"] * item["qty"] total += subtotal print(f"{item['name']:<10} x{item['qty']} = ${subtotal:.2f}") print(f"\nTotal: ${total:.2f}") # Remove itemcart.pop(1) # Xóa Bananaprint("\nAfter removing Banana:", len(cart), "items")
3. Student Grade Manager
# Danh sách điểmgrades = [85, 90, 78, 92, 88, 76, 95] # Thống kêhighest = max(grades)lowest = min(grades)average = sum(grades) / len(grades)passing = len([g for g in grades if g >= 80]) print(f"Highest: {highest}")print(f"Lowest: {lowest}")print(f"Average: {average:.2f}")print(f"Passing (>=80): {passing}/{len(grades)}") # Sắp xếpgrades.sort(reverse=True)print(f"\nTop 3: {grades[:3]}")
Bài Tập Thực Hành
Bài 1: List Operations
Tạo list numbers = [10, 20, 30, 40, 50]:
- Thêm 60 vào cuối
- Thêm 5 vào đầu
- Xóa 30
- In list đảo ngược
Bài 2: Unique Items
Viết chương trình xóa phần tử trùng lặp trong list:
- Input:
[1, 2, 2, 3, 4, 4, 5] - Output:
[1, 2, 3, 4, 5]
Bài 3: List Statistics
Cho list số, tính:
- Tổng
- Trung bình
- Max, Min
- Số chẵn, lẻ
Bài 4: Shopping List
Tạo shopping list app:
- Add item
- Remove item
- Show all items
- Clear all
Bài 5: Merge Sorted Lists
Gộp 2 sorted lists thành 1 sorted list:
list1 = [1, 3, 5]list2 = [2, 4, 6]- Output:
[1, 2, 3, 4, 5, 6]
Tóm Tắt
✅ List là collection có thứ tự, mutable
✅ Tạo list: [], list(), list comprehension
✅ Indexing: list[0], list[-1]
✅ Slicing: list[start:stop:step]
✅ Thêm: append(), extend(), insert(), +
✅ Xóa: remove(), pop(), del, clear()
✅ Methods: index(), count(), sort(), reverse(), copy()
Bài Tiếp Theo
Bài 5.2: Lists (Phần 2) - List comprehension, nested lists, sorting nâng cao, và list trong thực tế.
Remember:
- Lists are mutable (có thể thay đổi)
- Indexing bắt đầu từ 0
append()vsextend()vsinsert()remove()vspop()vsdelvsclear()- Slicing tạo copy mới, reference thì không!