18. Dữ liệu kiểu Danh sách
Ở các bài học trước, bạn đã thực hành với một số kiểu dữ liệu cơ bản của Python như kiểu số nguyên (integer), số thực (float), kiểu chuỗi (string), kiểu boolean.
Với kiểu dữ liệu cơ bản, bạn chỉ lưu được một giá trị trong một biến, như ten = "Teo" hay tuoi = 14. Nhưng nếu bạn muốn lưu tên của cả 40 bạn trong lớp thì sao? Việc tạo ra 40 biến khác nhau sẽ rất bất tiện.
Trong bài học này, chúng ta sẽ tìm hiểu một kiểu dữ liệu của Python, nó giúp bạn có thể lưu và xử lý dễ dàng một danh sách các bạn trong lớp, đó là kiểu Danh sách (List).
18.1 Danh sách là gì?
Trong Python, Danh sách là một kiểu dữ liệu dùng để lưu trữ một tập hợp các phần tử (có thể cùng hoặc khác kiểu dữ liệu) trong một biến duy nhất. Đây là một trong những cấu trúc dữ liệu phổ biến và linh hoạt nhất của Python.
Đặc điểm của kiểu dữ liệu Danh sách:
- Các phần tử trong Danh sách được sắp xếp theo một thứ tự xác định. Khi bạn thêm phần tử mới, chúng thường được đặt ở cuối danh sách
- Bạn có thể sửa đổi, thêm hoặc xóa các phần tử sau khi Danh sách đã được tạo
- Một Danh sách có thể chứa nhiều phần tử có cùng giá trị (cho phép giá trị trùng nhau)
- Một Danh sách có thể chứa số, chuỗi, boolean, hoặc thậm chí là một Danh sách khác
Cách định nghĩa một Danh sách:
Danh sách được định nghĩa bằng cặp ngoặc vuông [], các phần tử bên trong cách nhau bởi dấu phẩy.
Ví dụ, bạn hãy lập trình và chạy đoạn mã sau:
trai_cay = ["táo", "chuối", "xoài", "táo"]
so_nguyen = [10, 20, 30, 40]
hon_hop = [1, "Python", True, 3.14]
print(trai_cay)
print(so_nguyen)
print(hon_hop)
Để tạo danh sách rỗng (chưa có phần tử nào), sử dụng lệnh sau:
danh_sach_rong = []
print(danh_sach_rong)
# (không có gì)
Để thêm một phần tử vào danh sách, sử dụng hàm append(). Phần tử mới thêm vào được đặt ở cuối danh sách.
Ví dụ:
danh_sach_rong = []
danh_sach_rong.append("cam")
print(danh_sach_rong)
# ["cam"]
Số phần tử của Danh sách
Để biết Danh sách đang có bao nhiêu phần tử, sử dụng hàm len().
Ví dụ,
print(len(trai_cay))
# 4
Cách truy cập các phần tử
Python sử dụng chỉ số (index) để quản lý các phần tử trong Danh sách. Mỗi phần tử được xác định bằng một chỉ số. Chỉ số đầu tiên có giá trị là 0 (tính từ trái sang phải), chỉ số thứ 2 có giá trị là 1,...v.v.
Ví dụ, bạn hãy lập trình và chạy các đoạn mã sau:
- Tạo một danh sách như sau
trai_cay = ["táo", "chuối", "xoài", "nhãn"]
- Ở danh sách trai_cay, phần tử “táo” sẽ có chỉ số là 0, phần tử “chuối” có chỉ số là 1, phần tử “xoài” có chỉ số là 2, …v.v.
Bạn có thể kiểm tra bằng lệnh sau:
print(trai_cay[0]) # táo
print(trai_cay[1]) # chuối
print(trai_cay[2]) # xoài
Mỗi vị trí trong danh sách có thể truy cập tới bằng 1 trong 2 cách:
- Cách [1] truy cập theo chỉ số dương (chiều từ trái sang phải), như ví dụ ở trên;
- Cách [2] truy cập theo chỉ số âm (chiều từ phải sang trái). Tính từ phải sang trái, phần tử cuối cùng sẽ có chỉ số là -1, phần tử kế tiếp có chỉ số là -2, …v.v.
Cụ thể:
Ví dụ, truy cập theo chỉ số âm:
print(trai_cay[-1]) # nhãn
print(trai_cay[-2]) # xoài
print(trai_cay[-3]) # chuối
Lưu ý:
Nếu truy cập chỉ số không tồn tại, Python sẽ báo lỗi IndexError
Ví dụ:
print(trai_cay[4]) # Lỗi! Vì danh sách chỉ có đến chỉ số 3
18.2 Truy cập một dãy phần tử
Trong Python, thay vì chỉ lấy ra một phần tử duy nhất, bạn có thể lấy ra một danh sách con từ danh sách ban đầu bằng cách chỉ định một khoảng chỉ số. Kết quả trả về sẽ là một danh sách mới chứa các phần tử trong khoảng bạn đã chọn.
Cú pháp cơ bản: ten_danh_sach[start:end]
Trong đó:
- start: Chỉ số bắt đầu (được bao gồm trong kết quả)
- end: Chỉ số kết thúc (không bao gồm trong kết quả)
Sau đây là một số tình huống sử dụng:
Truy cập một khoảng ở giữa
Ví dụ: Lấy ra phần tử thứ 3, thứ 4 và thứ 5 trong danh sách.
trai_cay = ["táo", "chuối", "anh đào", "cam", "kiwi", "dưa hấu", "xoài"]
Lấy từ chỉ số 2 đến sát chỉ số 5 (tức là lấy index 2, 3, 4)
print(trai_cay[2:5])
# Kết quả: ['anh đào', 'cam', 'kiwi']
Bỏ trống chỉ số bắt đầu
Nếu bạn bỏ trống giá trị start, Python sẽ mặc định bắt đầu từ phần tử đầu tiên (chỉ số 0).
Cú pháp:
ten_danh_sach[:end]
Ví dụ: Lấy các phần tử từ đầu đến (nhưng không bao gồm) "kiwi".
trai_cay = ["táo", "chuối", "anh đào", "cam", "kiwi", "dưa hấu", "xoài"]
print(trai_cay[:4])
# Kết quả: ['táo', 'chuối', 'anh đào', 'cam']
Bỏ trống chỉ số kết thúc
Nếu bạn bỏ trống giá trị end, Python sẽ lấy từ chỉ số bắt đầu cho đến phần tử cuối cùng của danh sách.
Cú pháp:
ten_danh_sach[start:]
Ví dụ: Lấy các phần tử từ "anh đào" đến hết danh sách.
trai_cay = ["táo", "chuối", "anh đào", "cam", "kiwi", "dưa hấu", "xoài"]
print(trai_cay[2:])
# Kết quả: ['anh đào', 'cam', 'kiwi', 'dưa hấu', 'xoài']
18.3 Bài tập và câu hỏi
Bài 18a. Người kiểm kho tài ba
Mục tiêu: Thực hành truy cập phần tử trong Danh sách và sử dụng lệnh if.
Yêu cầu:
- Bạn có một danh sách các mặt hàng trong kho: kho_hang = ["tao", "xoai", "le", "dao"]
- Cho người dùng nhập vào tên một loại trái cây
- Duyệt qua từng phần tử của danh sách để kiểm tra xem trái cây đó có trong kho hay không
- Nếu có, in ra: "Mặt hàng này đang có sẵn". Nếu không, in ra: "Rất tiếc, kho đã hết hàng"
Kết quả mong đợi:
- Nhập: tao
Kết quả: Mặt hàng này đang có sẵn
- Nhập: man
Kết quả: Rất tiếc, kho đã hết hàng
Bài 18b. Chỉnh sửa danh sách lớp
Mục tiêu: Thực hành vòng lặp for để duyệt danh sách và các phương thức xử lý chuỗi.
Yêu cầu:
- Một danh sách tên học sinh bị viết hoa, viết thường lộn xộn: hoc_sinh = ["an", "bInH", "chi", "DUNG"]
- Hãy dùng vòng lặp để duyệt qua từng tên trong danh sách
- Sử dụng phương thức chuỗi để chuyển tất cả các tên về dạng: Chữ cái đầu viết hoa, các chữ sau viết thường (Ví dụ: an thành An)
- In danh sách mới đã được chuẩn hóa ra màn hình
Gợi ý: Sử dụng hàm capitalize() hoặc title() để định dạng lại chuỗi
Kết quả mong đợi: ['An', 'Binh', 'Chi', 'Dung']
Bài 18c. Máy lọc số điện thoại
Mục tiêu: Kết hợp vòng lặp, lệnh if...else và xử lý danh sách để giải quyết bài toán thực tế.
Yêu cầu:
- Bạn nhận được một danh sách các đầu số đăng ký: data = ["090123", "081456", "090789", "033111", "090555"]
- Hãy tạo một danh sách trống mới có tên là mobifone
- Duyệt qua danh sách data, nếu số nào bắt đầu bằng đầu số "090", hãy thêm số đó vào danh sách mobifone
- Sau khi lọc xong, hãy in ra tổng số lượng khách hàng dùng đầu số 090 và danh sách chi tiết các số đó
Gợi ý:
- Sử dụng phương thức .startswith("090") để kiểm tra đầu số
- Sử dụng phương thức .append() để thêm phần tử vào danh sách mới
- Sử dụng hàm len() để đếm số lượng phần tử
Kết quả mong đợi:
- Tìm thấy 3 khách hàng dùng đầu số 090
- Danh sách: ['090123', '090789', '090555']
Câu hỏi ôn tập
Câu hỏi 18.1: Nói về chỉ số (index) trong Danh sách. Phát biểu nào sau đây không đúng?
A. Chỉ số đầu tiên của danh sách luôn bắt đầu từ số 0
B. Chỉ số âm -1 dùng để truy cập vào phần tử cuối cùng của danh sách
C. Nếu bạn truy cập vào một chỉ số không tồn tại (ví dụ trai_cay[10] trong khi danh sách chỉ có 3 phần tử), Python sẽ tự động lấy phần tử cuối cùng
D. Mỗi phần tử trong danh sách có thể được truy cập bằng cả chỉ số dương và chỉ số âm
Câu hỏi 18.2: Cho đoạn mã sau: numbers = [10, 20, 30, 40, 50]. Kết quả của lệnh print(numbers[1:4]) là gì?
A. [10, 20, 30]
B. [20, 30, 40]
C. [20, 30, 40, 50]
D. [10, 20, 30, 40]
Câu hỏi 18.3: Để lấy toàn bộ các phần tử từ vị trí thứ 3 (chỉ số 2) cho đến hết danh sách, bạn sử dụng cú pháp nào?
A. danh_sach[2:]
B. danh_sach[:2]
C. danh_sach[2:end]
D. danh_sach[3:]
-----
18. List Data Type
In previous lessons, you practiced with several basic Python data types: integers, floats, strings, and booleans.
With basic data types, you can only store one value in a single variable, such as name = "Teo" or age = 14. But what if you want to store the names of all 40 students in your class? Creating 40 different variables would be very inconvenient.
In this lesson, we will explore a Python data type that allows you to store and easily manage a collection of items: the List.
18.1 What is a List?
In Python, a List is a data type used to store a collection of items (which can be of the same or different data types) in a single variable. This is one of Python's most popular and flexible data structures.
Characteristics of a List:
- Ordered: Items in a List have a defined order. When you add new items, they are typically placed at the end of the list.
- Mutable: You can modify, add, or remove items after the List has been created.
- Allow Duplicates: A List can contain multiple items with the same value.
- Diverse Data Types: A List can contain numbers, strings, booleans, or even other Lists.
Defining a List:
Lists are defined using square brackets [], with items separated by commas.
Example: Try coding and running the following:
fruits = ["apple", "banana", "mango", "apple"]
integers = [10, 20, 30, 40]
mixed = [1, "Python", True, 3.14]
print(fruits)
print(integers)
print(mixed)
To create an empty list (a list with no items), use:
empty_list = []
print(empty_list) # Output: []
To add an item to a list, use the append() method. The new item will be placed at the end of the list.
empty_list = []
empty_list.append("orange")
print(empty_list) # Output: ["orange"]
List Length:
To find out how many items are in a List, use the len() function.
print(len(fruits))
# Output: 4
Accessing Elements
Python uses indexes to manage items within a List. Each item is identified by an index. The first item has an index of 0, the second has an index of 1, and so on.
Example:
fruits = ["apple", "banana", "mango", "longan"]
# "apple" is at index 0, "banana" is at index 1, etc.
print(fruits[0]) # apple
print(fruits[1]) # banana
print(fruits[2]) # mango
Each position in a list can be accessed in two ways:
[1] Positive Indexing: Counting from left to right (starting at 0).
[2] Negative Indexing: Counting from right to left. The last item has an index of -1, the second to last is -2, and so on.
Example using negative indexes:
print(fruits[-1]) # longan
print(fruits[-2]) # mango
Note: If you try to access an index that does not exist, Python will raise an IndexError.
print(fruits[4])
# Error! Because the list only goes up to index 3.
18.2 Accessing a Range of Elements
Instead of grabbing just one item, you can extract a "sub-list" by specifying a range of indexes. This returns a new list containing the selected items.
Basic Syntax: list_name[start:end]
- start: Starting index (included in the result).
- end: Ending index (NOT included in the result).
Accessing a range in the middle:
Example: Get the 3rd, 4th, and 5th items.
fruits = ["apple", "banana", "cherry", "orange", "kiwi", "melon", "mango"]
# Get from index 2 up to (but not including) index 5
print(fruits[2:5])
# Output: ['cherry', 'orange', 'kiwi']
Leaving out the start index:
If you leave start blank, Python starts from the first item (index 0).
print(fruits[:4])
# Output: ['apple', 'banana', 'cherry', 'orange']
Leaving out the end index:
If you leave end blank, Python includes everything from the start index to the end of the list.
print(fruits[2:])
# Output: ['cherry', 'orange', 'kiwi', 'melon', 'mango']
18.3 Exercises and Review
Exercise 18a. The Inventory Expert
Goal: Practice accessing List elements and using if statements.
Requirement:
- You have a list of stock: inventory = ["apple", "mango", "pear", "peach"].
- Ask the user to input the name of a fruit.
- Check if that fruit exists in the inventory.
- If it exists, print: "This item is in stock." If not, print: "Sorry, out of stock."
Exercise 18b. Clean Up the Class List
Goal: Practice for loops and string methods.
Requirement:
- A list of student names with messy capitalization: students = ["an", "bInH", "chi", "DUNG"].
- Use a loop to iterate through each name.
- Use a string method to format each name: Capitalize the first letter, lowercase the rest (e.g., "an" becomes "An").
- Print the new, standardized list.
Exercise 18c. Phone Number Filter
Goal: Combine loops, if...else, and list processing.
Requirement:
- You receive a list of registrations: data = ["090123", "081456", "090789", "033111", "090555"].
- Create a new empty list named mobifone.
- Iterate through data. If a number starts with "090", add it to the mobifone list.
- Print the total count of 090 customers and the detailed list.
Review Questions
Q18.1: Regarding List indexes, which statement is FALSE?
A. The first index always starts at 0.
B. Index -1 is used to access the last item.
C. If you access a non-existent index (e.g., fruits[10] in a 3-item list), Python automatically grabs the last item.
D. Every item can be accessed using both a positive and a negative index.
Q18.2: Given numbers = [10, 20, 30, 40, 50], what is the output of print(numbers[1:4])?
A. [10, 20, 30]
B. [20, 30, 40]
C. [20, 30, 40, 50]
D. [10, 20, 30, 40]
Q18.3: To get all items from the 3rd position (index 2) to the end, which syntax do you use?
A. my_list[2:]
B. my_list[:2]
C. my_list[2:end]
D. my_list[3:]