ปัญหา
ต้องการทำการคำนวณต่างๆ (ค่าต่ำสุด, สูงสุด, เรียงลำดับ) กับข้อมูลใน dictionary
โซลูชัน
สร้าง dictionary ผู้เล่นเทนนิสและจำนวนแกรนด์สแลม
PlayerTitles = {
'Federer': 20,
'Nadal': 20,
'Djokovic': 17,
'Murray': 3,
'Theim': 1,
'Zverev': 0
}
1. หาค่าต่ำสุด (ผิด - เปรียบเทียบ key)
min(PlayerTitles) # 'Djokovic' (string comparison) ❌
2. หาค่าต่ำสุดของ values (ได้แค่ค่า ไม่รู้ key)
min(PlayerTitles.values()) # 0 ❌
3. หา key ที่มีค่าต่ำสุด (ใช้ key function)
min(PlayerTitles, key=lambda k: PlayerTitles[k]) # 'Zverev' ✓
# ต้อง lookup อีกครั้งเพื่อได้ค่า
min_titles = PlayerTitles[min(PlayerTitles, key=lambda k: PlayerTitles[k])] # 0
4. วิธีที่ดีที่สุด: ใช้ zip() สร้าง (value, key) pairs
Tuple เปรียบเทียบค่าแรกก่อน (value) ตามด้วย key → ได้พฤติกรรมที่ต้องการในคำสั่งเดียว
min_titles = min(zip(PlayerTitles.values(), PlayerTitles.keys())) # (0, 'Zverev')
max_titles = max(zip(PlayerTitles.values(), PlayerTitles.keys())) # (20, 'Nadal')
print(min_titles, max_titles)
5. เรียงลำดับข้อมูล
titles_sorted = sorted(zip(PlayerTitles.values(), PlayerTitles.keys()))
# [(0, 'Zverev'), (1, 'Theim'), (3, 'Murray'), (17, 'Djokovic'), (20, 'Federer'), (20, 'Nadal')]
6. ข้อควรระวัง: zip() เป็น iterator ใช้ได้ครั้งเดียว
titles_and_players = zip(PlayerTitles.values(), PlayerTitles.keys())
min(titles_and_players) # (0, 'Zverev')
max(titles_and_players) # ValueError: max() arg is an empty sequence ❌
ต้องสร้าง zip ใหม่ทุกครั้ง หรือแปลงเป็น list ก่อน
7. พฤติกรรมเมื่อค่าเท่ากัน (tie-breaking)
ใน (value, key) pairs ถ้า value เท่ากัน จะเปรียบเทียบ key ด้วย alphabetical order
ตัวอย่าง: Federer และ Nadal ค่า 20 เท่ากัน → max() คืน (20, 'Nadal') เพราะ 'Nadal' > 'Federer' ตาม alphabet
สรุป
- ใช้
zip(values(), keys())สร้าง (value, key) pairs - ใช้กับ
min(),max(),sorted()ได้ในคำสั่งเดียว - ระวัง zip iterator ใช้ครั้งเดียว
- key ใช้ tie-break เมื่อ value เท่ากัน