Indexing List trong Python

Python Tutorial | by Hoc Python

Trong lập trình Python, List (danh sách) là một trong những cấu trúc dữ liệu linh hoạt và được sử dụng phổ biến nhất. Nó cho phép chúng ta lưu trữ một tập hợp các mục có thứ tự, từ số, chuỗi cho đến các đối tượng phức tạp hơn. Tuy nhiên, để làm việc hiệu quả với các danh sách này, việc hiểu rõ cách truy cập và thao tác với từng phần tử riêng lẻ là vô cùng quan trọng.

Đó chính là lúc khái niệm "Indexing" trở nên cần thiết. Indexing là một kỹ thuật mạnh mẽ giúp chúng ta xác định vị trí và tương tác với các phần tử trong List dựa trên chỉ số của chúng. Cho dù bạn muốn lấy một giá trị cụ thể, thay đổi một phần tử, hay đơn giản là kiểm tra nội dung của danh sách, Indexing sẽ là công cụ không thể thiếu.

Trong bài viết này, chúng ta sẽ cùng nhau tìm hiểu Indexing List trong Python từ những kiến thức cơ bản nhất, giúp bạn dễ dàng nắm bắt và áp dụng vào các dự án của mình. Hãy cùng bắt đầu nhé!

Giới thiệu về List trong Python

List (danh sách) là một trong những cấu trúc dữ liệu cơ bản và mạnh mẽ nhất trong Python. Nó cho phép bạn lưu trữ một tập hợp các mục (item) có thứ tự . Điều đặc biệt là List có thể chứa các kiểu dữ liệu khác nhau trong cùng một danh sách, ví dụ như số nguyên, chuỗi, số thực, giá trị boolean, thậm chí là các List khác.

List là gì?

Về bản chất, List là một "container" (thùng chứa) dùng để giữ nhiều giá trị trong một biến duy nhất, thay vì phải tạo ra nhiều biến riêng lẻ. Tưởng tượng List như một chiếc hộp lớn có nhiều ngăn kéo, và mỗi ngăn kéo chứa một món đồ khác nhau. Các món đồ này được sắp xếp theo một thứ tự nhất định.

List trong Python được định nghĩa bằng cách đặt các phần tử trong cặp dấu ngoặc vuông [], và các phần tử được ngăn cách bởi dấu phẩy ,.

Ví dụ minh họa List

Hãy xem xét một vài ví dụ để hiểu rõ hơn về cách tạo và nội dung của List:

List chứa các số nguyên:

diem_so = [8, 9, 7, 10, 6]
print(diem_so)
# Output: [8, 9, 7, 10, 6]

List chứa các chuỗi:

hoa_qua = ["táo", "chuối", "cam", "xoài"]
print(hoa_qua)
# Output: ['táo', 'chuối', 'cam', 'xoài']

List chứa nhiều kiểu dữ liệu khác nhau (phổ biến trong Python):

thong_tin_sinh_vien = ["Nguyễn Văn A", 20, True, 7.5]
print(thong_tin_sinh_vien)
# Output: ['Nguyễn Văn A', 20, True, 7.5]

Trong ví dụ này, thong_tin_sinh_vien chứa một chuỗi (tên), một số nguyên (tuổi), một giá trị boolean (là sinh viên?), và một số thực (điểm trung bình).

List rỗng (không có phần tử nào):

danh_sach_rong = []
print(danh_sach_rong)
# Output: []

Tại sao cần List?

List không chỉ là một cách tiện lợi để lưu trữ dữ liệu mà còn mang lại nhiều lợi ích quan trọng trong lập trình:

Tổ chức dữ liệu hiệu quả: Thay vì tạo hàng loạt biến riêng lẻ (ví dụ sinh_vien1, sinh_vien2,...), bạn có thể nhóm tất cả các phần tử liên quan vào một List duy nhất. Điều này giúp mã nguồn gọn gàng và dễ quản lý hơn rất nhiều.

# Không dùng List (kém hiệu quả)
ten_sv1 = "An"
tuoi_sv1 = 18
ten_sv2 = "Bình"
tuoi_sv2 = 19

# Dùng List (hiệu quả hơn)
danh_sach_sinh_vien = ["An", 18, "Bình", 19] # Hoặc tốt hơn là list chứa dict/object

Dễ dàng lặp (iterate) qua các phần tử: Khi dữ liệu được tổ chức trong List, bạn có thể dễ dàng duyệt qua từng phần tử một bằng các vòng lặp (như for loop) để thực hiện các thao tác như hiển thị, tính toán, hoặc lọc dữ liệu.

diem_thi = [7, 8, 9, 6, 10]
print("Điểm thi của học sinh:")
for diem in diem_thi:
    print(diem)
# Output:
# Điểm thi của học sinh:
# 7
# 8
# 9
# 6
# 10

Thay đổi và thao tác linh hoạt: List là một cấu trúc dữ liệu có thể thay đổi (mutable). Điều này có nghĩa là sau khi bạn tạo một List, bạn vẫn có thể thêm phần tử mới vào, xóa bớt phần tử, hoặc sửa đổi giá trị của các phần tử hiện có một cách dễ dàng.

tasks = ["làm bài tập", "đi chợ", "nấu cơm"]
print("Danh sách công việc ban đầu:", tasks)

# Thêm một công việc mới
tasks.append("gọi điện thoại")
print("Sau khi thêm:", tasks)

# Xóa một công việc
tasks.remove("đi chợ")
print("Sau khi xóa:", tasks)

# Sửa đổi một công việc (sẽ học kỹ hơn trong phần Indexing)
tasks[0] = "hoàn thành báo cáo"
print("Sau khi sửa đổi:", tasks)

Nhờ những đặc tính này, List trở thành một công cụ không thể thiếu cho bất kỳ lập trình viên Python nào, từ việc quản lý danh sách sản phẩm trong một cửa hàng trực tuyến đến việc xử lý dữ liệu phức tạp trong phân tích khoa học.

Indexing là gì?

Indexing là quá trình sử dụng các con số (gọi là chỉ số hay index) để xác định và truy cập từng phần tử riêng lẻ bên trong một List (hoặc các cấu trúc dữ liệu có thứ tự khác như chuỗi, tuple).

Hãy hình dung List của bạn như một dãy ghế trong rạp chiếu phim, mỗi ghế có một số hiệu riêng. Indexing chính là việc bạn dùng số hiệu ghế đó để tìm đúng người đang ngồi trên chiếc ghế bạn muốn. Trong Python, các chỉ số này bắt đầu từ 0 đối với phần tử đầu tiên, tăng dần lên 1 cho mỗi phần tử tiếp theo.

Ví dụ:

mon_an = ["phở", "bún chả", "nem", "cháo"]

# Chỉ số (index) của "phở" là 0
# Chỉ số (index) của "bún chả" là 1
# Chỉ số (index) của "nem" là 2
# Chỉ số (index) của "cháo" là 3

Để truy cập một phần tử, bạn chỉ cần đặt chỉ số của nó trong cặp dấu ngoặc vuông [] ngay sau tên List:

print(mon_an[0]) # Output: phở
print(mon_an[2]) # Output: nem

Tầm quan trọng của Indexing

Indexing đóng vai trò cực kỳ quan trọng vì nó là nền tảng giúp chúng ta thao tác linh hoạt với dữ liệu trong List. Dưới đây là những lý do chính:

Truy xuất dữ liệu cụ thể: Indexing cho phép bạn lấy ra chính xác giá trị của một phần tử mà bạn cần, mà không cần phải duyệt qua toàn bộ List. Điều này đặc biệt hữu ích khi List có kích thước lớn.

thong_tin_ca_nhan = ["Lan Anh", 25, "Hà Nội", "[email protected]"]
# Muốn biết tên:
ten = thong_tin_ca_nhan[0]
print("Tên:", ten) # Output: Tên: Lan Anh

# Muốn biết email:
email = thong_tin_ca_nhan[3]
print("Email:", email) # Output: Email: [email protected]

Thay đổi (cập nhật) giá trị phần tử: List là cấu trúc dữ liệu có thể thay đổi (mutable). Indexing giúp bạn định vị và thay thế giá trị của một phần tử cụ thể bằng một giá trị mới.

danh_sach_cong_viec = ["mua sữa", "giặt đồ", "học Python"]
print("Trước khi thay đổi:", danh_sach_cong_viec)

# Đã hoàn thành "giặt đồ", muốn thay bằng "đã giặt đồ"
danh_sach_cong_viec[1] = "đã giặt đồ"
print("Sau khi thay đổi:", danh_sach_cong_viec)
# Output: Sau khi thay đổi: ['mua sữa', 'đã giặt đồ', 'học Python']

Hỗ trợ các phép toán phức tạp hơn: Nhiều thuật toán và thao tác dữ liệu nâng cao dựa trên khả năng truy cập từng phần tử của List thông qua Indexing. Ví dụ, khi bạn muốn đảo ngược một List, sắp xếp các phần tử, hoặc tìm kiếm một giá trị, bạn thường sẽ sử dụng Indexing để tương tác với các phần tử tại các vị trí nhất định.

# Ví dụ đơn giản: Đảo ngược vị trí 2 phần tử đầu tiên
so_lieu = [10, 20, 30]
# Hoán đổi giá trị
temp = so_lieu[0]
so_lieu[0] = so_lieu[1]
so_lieu[1] = temp
print(so_lieu) # Output: [20, 10, 30]

(Lưu ý: Python có các phương thức dễ hơn để hoán đổi hoặc đảo ngược List, ví dụ trên chỉ để minh họa ứng dụng của Indexing).

Các loại Indexing cơ bản trong Python

Khi làm việc với List trong Python, có hai cách chính để xác định vị trí của một phần tử: sử dụng chỉ số dương hoặc chỉ số âm.

Positive Indexing (Chỉ số dương)

Khái niệm: Positive Indexing là cách truy cập các phần tử của List bằng cách đếm từ bên trái sang phải, bắt đầu từ chỉ số 0. Đây là phương pháp phổ biến và trực quan nhất.

Ví dụ minh họa chi tiết:

  • Chỉ số 0: Luôn luôn là chỉ số của phần tử đầu tiên trong List.

  • Chỉ số 1: Là chỉ số của phần tử thứ hai.

  • Và cứ thế tiếp tục: chỉ số n sẽ là của phần tử thứ n+1.

# Tạo một danh sách các loại trái cây
fruits = ["apple", "banana", "cherry", "orange", "kiwi"]

# "apple" ở chỉ số 0
# "banana" ở chỉ số 1
# "cherry" ở chỉ số 2
# "orange" ở chỉ số 3
# "kiwi" ở chỉ số 4

print(f"Phần tử ở chỉ số 0 là: {fruits[0]}") # Output: Phần tử ở chỉ số 0 là: apple
print(f"Phần tử ở chỉ số 1 là: {fruits[1]}") # Output: Phần tử ở chỉ số 1 là: banana
print(f"Phần tử ở chỉ số 2 là: {fruits[2]}") # Output: Phần tử ở chỉ số 2 là: cherry
print(f"Phần tử ở chỉ số 4 là: {fruits[4]}") # Output: Phần tử ở chỉ số 4 là: kiwi

Bạn cũng có thể sử dụng positive indexing để thay đổi giá trị của một phần tử tại vị trí cụ thể:

colors = ["red", "green", "blue"]
print(f"Danh sách màu ban đầu: {colors}") # Output: Danh sách màu ban đầu: ['red', 'green', 'blue']

# Thay đổi phần tử ở chỉ số 1 (là "green") thành "yellow"
colors[1] = "yellow"
print(f"Danh sách màu sau khi thay đổi: {colors}") # Output: Danh sách màu sau khi thay đổi: ['red', 'yellow', 'blue']

Negative Indexing (Chỉ số âm)

Khái niệm: Negative Indexing là cách truy cập các phần tử của List bằng cách đếm từ bên phải sang trái, bắt đầu từ chỉ số -1. Phương pháp này đặc biệt hữu ích khi bạn muốn truy cập các phần tử cuối cùng của List mà không cần biết độ dài chính xác của nó.

Ví dụ minh họa chi tiết:

  • Chỉ số -1: Luôn luôn là chỉ số của phần tử cuối cùng trong List.

  • Chỉ số -2: Là chỉ số của phần tử kế cuối.

  • Và cứ thế tiếp tục: chỉ số -n sẽ là của phần tử thứ n tính từ cuối List lên.

# Tạo một danh sách các con số
numbers = [10, 20, 30, 40, 50]

# 50 ở chỉ số -1 (phần tử cuối cùng)
# 40 ở chỉ số -2 (phần tử kế cuối)
# 30 ở chỉ số -3
# 20 ở chỉ số -4
# 10 ở chỉ số -5

print(f"Phần tử ở chỉ số -1 là: {numbers[-1]}") # Output: Phần tử ở chỉ số -1 là: 50
print(f"Phần tử ở chỉ số -2 là: {numbers[-2]}") # Output: Phần tử ở chỉ số -2 là: 40
print(f"Phần tử ở chỉ số -5 là: {numbers[-5]}") # Output: Phần tử ở chỉ số -5 là: 10

Tương tự như positive indexing, bạn cũng có thể dùng negative indexing để thay đổi giá trị:

tasks = ["học bài", "tập thể dục", "đọc sách", "nấu ăn"]
print(f"Danh sách công việc ban đầu: {tasks}") # Output: Danh sách công việc ban đầu: ['học bài', 'tập thể dục', 'đọc sách', 'nấu ăn']

# Thay đổi phần tử cuối cùng (ở chỉ số -1, là "nấu ăn") thành "nghỉ ngơi"
tasks[-1] = "nghỉ ngơi"
print(f"Danh sách công việc sau khi thay đổi: {tasks}") # Output: Danh sách công việc sau khi thay đổi: ['học bài', 'tập thể dục', 'đọc sách', 'nghỉ ngơi']

Việc hiểu và sử dụng cả hai loại chỉ số này sẽ giúp bạn thao tác với List một cách linh hoạt và hiệu quả hơn rất nhiều trong các chương trình Python.

Thực hành Indexing trong Python

Phần này sẽ đi sâu vào cách bạn có thể sử dụng indexing để truy cập và thay đổi các phần tử trong List, cũng như một lỗi phổ biến cần tránh.

Truy cập một phần tử

Để lấy giá trị của một phần tử cụ thể trong List, bạn chỉ cần sử dụng tên List theo sau là dấu ngoặc vuông [] chứa chỉ số (index) của phần tử đó.

Cú pháp: list_name[index]

Ví dụ:

# Danh sách các ngày trong tuần
days_of_week = ["Thứ Hai", "Thứ Ba", "Thứ Tư", "Thứ Năm", "Thứ Sáu", "Thứ Bảy", "Chủ Nhật"]

# Lấy phần tử đầu tiên (chỉ số 0)
first_day = days_of_week[0]
print(f"Ngày đầu tuần là: {first_day}") # Output: Ngày đầu tuần là: Thứ Hai

# Lấy phần tử ở giữa (chỉ số 3)
mid_week_day = days_of_week[3]
print(f"Giữa tuần là: {mid_week_day}") # Output: Giữa tuần là: Thứ Năm

# Lấy phần tử cuối cùng (sử dụng chỉ số âm)
last_day = days_of_week[-1]
print(f"Ngày cuối tuần là: {last_day}") # Output: Ngày cuối tuần là: Chủ Nhật

Bạn có thể lưu giá trị được truy cập vào một biến mới hoặc sử dụng nó trực tiếp trong biểu thức.

Thay đổi giá trị phần tử

Vì List là một cấu trúc dữ liệu có thể thay đổi (mutable), bạn hoàn toàn có thể cập nhật giá trị của một phần tử tại một chỉ số cụ thể.

Cú pháp: list_name[index] = new_value

Ví dụ:

# Danh sách điểm số của học sinh
scores = [7, 8, 9, 7.5, 6]
print(f"Điểm số ban đầu: {scores}") # Output: Điểm số ban đầu: [7, 8, 9, 7.5, 6]

# Giả sử học sinh có điểm 8 (ở chỉ số 1) được chấm lại thành 8.5
scores[1] = 8.5
print(f"Điểm số sau khi cập nhật điểm thứ hai: {scores}") # Output: Điểm số sau khi cập nhật điểm thứ hai: [7, 8.5, 9, 7.5, 6]

# Thay đổi phần tử cuối cùng từ 6 thành 9 (sử dụng chỉ số âm)
scores[-1] = 9
print(f"Điểm số sau khi cập nhật điểm cuối cùng: {scores}") # Output: Điểm số sau khi cập nhật điểm cuối cùng: [7, 8.5, 9, 7.5, 9]

# Thay đổi nhiều phần tử bằng cách gán giá trị mới riêng lẻ
tasks = ["mua sữa", "giặt đồ", "nấu cơm"]
print(f"Công việc ban đầu: {tasks}") # Output: Công việc ban đầu: ['mua sữa', 'giặt đồ', 'nấu cơm']
tasks[0] = "hoàn thành báo cáo"
tasks[2] = "tập thể dục"
print(f"Công việc sau khi thay đổi: {tasks}") # Output: Công việc sau khi thay đổi: ['hoàn thành báo cáo', 'giặt đồ', 'tập thể dục']

Lỗi thường gặp: IndexError

Khi bạn cố gắng truy cập hoặc thay đổi một phần tử bằng một chỉ số không tồn tại trong phạm vi của List, Python sẽ báo lỗi IndexError: list index out of range.

Điều này xảy ra khi chỉ số bạn cung cấp:

  • Lớn hơn hoặc bằng độ dài của List (khi dùng chỉ số dương).

  • Nhỏ hơn giá trị âm của độ dài List (khi dùng chỉ số âm).

Ví dụ:

programming_languages = ["Python", "Java", "C++"]
# Độ dài của list này là 3.
# Các chỉ số hợp lệ là: 0, 1, 2 (dương) và -1, -2, -3 (âm).

# Ví dụ lỗi IndexError khi chỉ số dương vượt quá giới hạn
# print(programming_languages[3])
# Lỗi sẽ là: IndexError: list index out of range
# Lý do: chỉ số 3 không tồn tại, vì chỉ số lớn nhất là 2.

# Ví dụ lỗi IndexError khi chỉ số âm vượt quá giới hạn
# print(programming_languages[-4])
# Lỗi sẽ là: IndexError: list index out of range
# Lý do: chỉ số -4 không tồn tại, vì chỉ số nhỏ nhất là -3.

Cách tránh lỗi IndexError:

  • Luôn kiểm tra độ dài List: Sử dụng hàm len() để lấy độ dài của List trước khi truy cập các chỉ số.

my_list = [10, 20]
if len(my_list) > 2: # Kiểm tra xem có phần tử ở chỉ số 2 không
    print(my_list[2])
else:
    print("Chỉ số 2 không tồn tại trong list này.")
# Output: Chỉ số 2 không tồn tại trong list này.
  • Sử dụng vòng lặp an toàn: Khi duyệt qua List, hãy sử dụng vòng lặp for trực tiếp trên các phần tử hoặc dùng range(len(list)) để đảm bảo bạn không vượt quá chỉ số.

Việc hiểu rõ cách sử dụng indexing và nhận biết lỗi IndexError là rất quan trọng để viết mã Python mạnh mẽ và không gặp lỗi.

Kết bài

Qua bài viết này, chúng ta đã cùng nhau tìm hiểu về List trong Python và cách sử dụng Indexing để truy cập, cũng như thay đổi các phần tử của nó. Chúng ta đã tìm hiểu hai loại chỉ số chính:

  • Positive Indexing (chỉ số dương): Bắt đầu từ 0 từ trái sang phải, giúp bạn truy cập phần tử theo thứ tự thông thường.

  • Negative Indexing (chỉ số âm): Bắt đầu từ -1 từ phải sang trái, cực kỳ tiện lợi khi bạn muốn thao tác với các phần tử ở cuối List.

Lưu ý quan trọng: List là một cấu trúc dữ liệu linh hoạt và có thể thay đổi (mutable), cho phép bạn chứa nhiều kiểu dữ liệu khác nhau (số, chuỗi, boolean, v.v.) và dễ dàng sửa đổi chúng sau khi tạo. Việc thành thạo Indexing là chìa khóa để khai thác sức mạnh này.

Bài viết liên quan