Vấn đề
Bạn muốn thực hiện các phép tính (giá trị nhỏ nhất, lớn nhất, sắp xếp...) trên dữ liệu dạng dictionary.
Giải pháp
Tạo dictionary ví dụ: tên vận động viên tennis và số cúp Grand Slam.
PlayerTitles = {
'Federer': 20,
'Nadal': 20,
'Djokovic': 17,
'Murray': 3,
'Theim': 1,
'Zverev': 0
}
1. Tìm giá trị nhỏ nhất (sai nếu dùng trực tiếp)
print(min(PlayerTitles)) # Kết quả: 'Djokovic' (so sánh key theo alphabet)
2. Dùng values() để lấy giá trị
print(min(PlayerTitles.values())) # Kết quả: 0
3. Tìm key tương ứng với giá trị min/max
# Dùng key function
min_key = min(PlayerTitles, key=lambda k: PlayerTitles[k])
print(min_key) # 'Zverev'
# Cần lookup thêm để lấy giá trị
min_titles = PlayerTitles[min(PlayerTitles, key=lambda k: PlayerTitles[k])]
print(min_titles) # 0
4. Giải pháp tối ưu: zip() để "đảo" dictionary
Tạo sequence các cặp (value, key). Khi so sánh tuple, Python so sánh phần tử đầu tiên (value) trước, rồi đến key.
min_titles = min(zip(PlayerTitles.values(), PlayerTitles.keys()))
max_titles = max(zip(PlayerTitles.values(), PlayerTitles.keys()))
print(min_titles, max_titles)
# Kết quả: (0, 'Zverev') (20, 'Nadal')
5. Sắp xếp với zip() và sorted()
titles_sorted = sorted(zip(PlayerTitles.values(), PlayerTitles.keys()))
print(titles_sorted)
# [(0, 'Zverev'), (1, 'Theim'), (3, 'Murray'), (17, 'Djokovic'), (20, 'Federer'), (20, 'Nadal')]
6. Lưu ý về zip() tạo iterator
titles_and_players = zip(PlayerTitles.values(), PlayerTitles.keys())
print(min(titles_and_players)) # (0, 'Zverev')
print(min(titles_and_players)) # Lỗi: iterator đã hết (empty sequence)
7. Xử lý trùng giá trị
Khi có giá trị trùng (như Federer và Nadal đều 20), min()/max() trên cặp (value, key) sẽ dùng key để quyết định (theo thứ tự alphabet). Do đó max trả về (20, 'Nadal') vì 'Nadal' > 'Federer'.