Ngôn ngữ Python
Dictionary & Set Comprehension

Dictionary và Set Comprehension

1. Giới thiệu

Comprehension là cách viết ngắn gọn và dễ đọc để tạo Dictionary và Set từ một iterable (list, tuple, range, v.v.).

Lợi ích của Comprehension:

  • ✅ Code ngắn gọn hơn
  • ✅ Dễ đọc và dễ hiểu
  • ✅ Thường nhanh hơn vòng lặp thông thường
  • ✅ Pythonic (theo phong cách Python)

2. Dictionary Comprehension

2.1 - Cú pháp cơ bản

# Cú pháp
new_dict = {key_expression: value_expression for item in iterable}

2.2 - Ví dụ đơn giản

# Tạo dictionary: số -> bình phương
squares = {x: x**2 for x in range(1, 6)}
print(squares)
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
 
# Tạo dictionary từ hai lists
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
students = {name: age for name, age in zip(names, ages)}
print(students)
# {'Alice': 25, 'Bob': 30, 'Charlie': 35}

2.3 - So sánh với vòng lặp thông thường

# Cách 1: Vòng lặp thông thường
squares = {}
for x in range(1, 6):
    squares[x] = x**2
 
# Cách 2: Dictionary Comprehension (ngắn gọn hơn!)
squares = {x: x**2 for x in range(1, 6)}

3. Dictionary Comprehension với điều kiện

3.1 - Thêm điều kiện if

# Chỉ lấy số chẵn
even_squares = {x: x**2 for x in range(1, 11) if x % 2 == 0}
print(even_squares)
# {2: 4, 4: 16, 6: 36, 8: 64, 10: 100}
 
# Lọc học sinh điểm cao
scores = {"Alice": 85, "Bob": 60, "Charlie": 92, "David": 55}
passed = {name: score for name, score in scores.items() if score >= 70}
print(passed)
# {'Alice': 85, 'Charlie': 92}

3.2 - Điều kiện if-else

# Phân loại số chẵn/lẻ
numbers = {x: ("even" if x % 2 == 0 else "odd") for x in range(1, 6)}
print(numbers)
# {1: 'odd', 2: 'even', 3: 'odd', 4: 'even', 5: 'odd'}
 
# Chuyển đổi nhiệt độ
temps_c = {"Ha Noi": 30, "Da Nang": 28, "TP HCM": 32}
temps_f = {city: (temp * 9/5 + 32 if temp else 0) for city, temp in temps_c.items()}
print(temps_f)
# {'Ha Noi': 86.0, 'Da Nang': 82.4, 'TP HCM': 89.6}

4. Ví dụ thực tế với Dictionary Comprehension

Ví dụ 1: Đếm ký tự trong chuỗi

text = "hello"
char_count = {char: text.count(char) for char in text}
print(char_count)
# {'h': 1, 'e': 1, 'l': 2, 'o': 1}

Ví dụ 2: Đảo ngược dictionary

original = {"a": 1, "b": 2, "c": 3}
reversed_dict = {value: key for key, value in original.items()}
print(reversed_dict)
# {1: 'a', 2: 'b', 3: 'c'}

Ví dụ 3: Chuyển đổi list thành lookup dictionary

fruits = ["apple", "banana", "cherry"]
fruit_index = {fruit: index for index, fruit in enumerate(fruits)}
print(fruit_index)
# {'apple': 0, 'banana': 1, 'cherry': 2}

Ví dụ 4: Tạo dictionary từ list với điều kiện

words = ["apple", "banana", "kiwi", "cherry", "date"]
long_words = {word: len(word) for word in words if len(word) > 5}
print(long_words)
# {'banana': 6, 'cherry': 6}

5. Nested Dictionary Comprehension

5.1 - Comprehension lồng nhau

# Tạo bảng cửu chương
multiplication_table = {
    x: {y: x*y for y in range(1, 6)}
    for x in range(1, 6)
}
print(multiplication_table)
# {
#     1: {1: 1, 2: 2, 3: 3, 4: 4, 5: 5},
#     2: {1: 2, 2: 4, 3: 6, 4: 8, 5: 10},
#     ...
# }

5.2 - Flatten nested dictionary

nested = {"a": {"x": 1, "y": 2}, "b": {"x": 3, "y": 4}}
flat = {f"{k1}_{k2}": v for k1, d in nested.items() for k2, v in d.items()}
print(flat)
# {'a_x': 1, 'a_y': 2, 'b_x': 3, 'b_y': 4}

6. Set Comprehension

6.1 - Cú pháp cơ bản

# Cú pháp
new_set = {expression for item in iterable}

Lưu ý: Set tự động loại bỏ phần tử trùng lặp!

6.2 - Ví dụ đơn giản

# Tạo set các số bình phương
squares = {x**2 for x in range(1, 6)}
print(squares)
# {1, 4, 9, 16, 25}
 
# Loại bỏ trùng lặp
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
unique = {x for x in numbers}
print(unique)
# {1, 2, 3, 4}

6.3 - So sánh với vòng lặp thông thường

# Cách 1: Vòng lặp thông thường
squares = set()
for x in range(1, 6):
    squares.add(x**2)
 
# Cách 2: Set Comprehension (ngắn gọn hơn!)
squares = {x**2 for x in range(1, 6)}

7. Set Comprehension với điều kiện

7.1 - Thêm điều kiện if

# Chỉ lấy số chẵn
even_numbers = {x for x in range(1, 11) if x % 2 == 0}
print(even_numbers)
# {2, 4, 6, 8, 10}
 
# Lọc từ dài hơn 4 ký tự
words = ["cat", "dog", "elephant", "lion", "tiger"]
long_words = {word for word in words if len(word) > 4}
print(long_words)
# {'elephant', 'tiger'}

7.2 - Điều kiện if-else

# Chuyển đổi: số chẵn thành "even", số lẻ thành "odd"
types = {"even" if x % 2 == 0 else "odd" for x in range(1, 6)}
print(types)
# {'odd', 'even'}  # Chỉ 2 phần tử vì set loại trùng lặp!

8. Ví dụ thực tế với Set Comprehension

Ví dụ 1: Lấy các ký tự unique trong chuỗi

text = "hello world"
unique_chars = {char for char in text if char != " "}
print(unique_chars)
# {'h', 'e', 'l', 'o', 'w', 'r', 'd'}

Ví dụ 2: Lấy phần tử chung của nhiều lists

list1 = [1, 2, 3, 4, 5]
list2 = [4, 5, 6, 7, 8]
common = {x for x in list1 if x in list2}
print(common)
# {4, 5}

Ví dụ 3: Tạo set các số chia hết cho 3 hoặc 5

divisible = {x for x in range(1, 31) if x % 3 == 0 or x % 5 == 0}
print(divisible)
# {3, 5, 6, 9, 10, 12, 15, 18, 20, 21, 24, 25, 27, 30}

Ví dụ 4: Tìm các từ xuất hiện trong cả hai văn bản

text1 = "Python is awesome and powerful"
text2 = "Python is easy and fun"
words1 = set(text1.lower().split())
words2 = set(text2.lower().split())
common_words = {word for word in words1 if word in words2}
print(common_words)
# {'python', 'is', 'and'}

9. Nested Set Comprehension

# Lấy tất cả các số từ nested lists
nested_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
all_numbers = {num for sublist in nested_lists for num in sublist}
print(all_numbers)
# {1, 2, 3, 4, 5, 6, 7, 8, 9}
 
# Lấy các số chẵn từ nested lists
even_numbers = {num for sublist in nested_lists for num in sublist if num % 2 == 0}
print(even_numbers)
# {2, 4, 6, 8}

10. So sánh Dictionary vs Set Comprehension

Đặc điểmDictionary ComprehensionSet Comprehension
Cú pháp{k: v for ...}{x for ...}
Kết quảDictionary (key-value)Set (unique values)
Trùng lặpKey trùng thì ghi đèTự động loại bỏ
Thứ tựGiữ thứ tự (Python 3.7+)Không có thứ tự
Sử dụngMapping, lookupUnique values, set operations

11. Tips và Best Practices

1. Khi nào nên dùng?

# TỐT - Đơn giản, dễ đọc
squares = {x: x**2 for x in range(5)}
 
# TRÁNH - Quá phức tạp, khó đọc
complex = {
    x: y**2 + z**3
    for x in range(10)
    for y in range(10)
    for z in range(10)
    if x > 5 and y < 3 and z % 2 == 0
}
# Nên dùng vòng lặp thông thường cho trường hợp này!

2. Đặt tên rõ ràng

# TỐT
student_grades = {name: score for name, score in zip(names, scores)}
 
# TRÁNH
d = {n: s for n, s in zip(names, scores)}  # Tên biến không rõ ràng

3. Giữ cho đơn giản

# TỐT - Một điều kiện đơn giản
even_squares = {x: x**2 for x in range(10) if x % 2 == 0}
 
# TRÁNH - Nhiều điều kiện phức tạp
# Nên dùng function hoặc vòng lặp thông thường
complex = {
    x: compute(x)
    for x in data
    if condition1(x) and condition2(x) or condition3(x)
}

4. Cẩn thận với nested comprehension

# TỐT - Flatten đơn giản
flat = {item for sublist in nested for item in sublist}
 
# TRÁNH - Quá nhiều lồng nhau
very_nested = {
    x: {
        y: {z: x*y*z for z in range(5)}
        for y in range(5)
    }
    for x in range(5)
}
# Khó đọc! Nên tách thành nhiều bước

12. Ví dụ tổng hợp

Ví dụ 1: Quản lý điểm học sinh

students = ["Alice", "Bob", "Charlie", "David", "Eve"]
scores = [85, 92, 78, 95, 88]
 
# Tạo dictionary điểm
grade_dict = {name: score for name, score in zip(students, scores)}
print(grade_dict)
 
# Lọc học sinh đạt từ 80 trở lên
excellent = {name: score for name, score in grade_dict.items() if score >= 80}
print(excellent)
# {'Alice': 85, 'Bob': 92, 'David': 95, 'Eve': 88}
 
# Tạo set tên học sinh đạt điểm cao
top_students = {name for name, score in grade_dict.items() if score >= 90}
print(top_students)
# {'Bob', 'David'}

Ví dụ 2: Phân tích văn bản

text = "Python is powerful and Python is easy to learn"
words = text.lower().split()
 
# Đếm số lần xuất hiện của mỗi từ
word_count = {word: words.count(word) for word in set(words)}
print(word_count)
# {'python': 2, 'is': 2, 'powerful': 1, 'and': 1, 'easy': 1, 'to': 1, 'learn': 1}
 
# Lấy các từ unique (không trùng)
unique_words = {word for word in words}
print(unique_words)
# {'python', 'is', 'powerful', 'and', 'easy', 'to', 'learn'}
 
# Lấy các từ dài hơn 4 ký tự
long_words = {word for word in words if len(word) > 4}
print(long_words)
# {'python', 'powerful', 'learn'}

Ví dụ 3: Chuyển đổi dữ liệu

# Dữ liệu gốc
products = [
    ("Laptop", 1000),
    ("Mouse", 20),
    ("Keyboard", 50),
    ("Monitor", 300)
]
 
# Tạo dictionary giá
prices = {name: price for name, price in products}
print(prices)
 
# Áp dụng giảm giá 10%
discounted = {name: price * 0.9 for name, price in prices.items()}
print(discounted)
# {'Laptop': 900.0, 'Mouse': 18.0, 'Keyboard': 45.0, 'Monitor': 270.0}
 
# Lấy sản phẩm đắt tiền (> 100)
expensive = {name for name, price in prices.items() if price > 100}
print(expensive)
# {'Laptop', 'Monitor'}

Bài giảng trên YouTube

Cập nhật sau


Lập trình Python - Bumbii Academy