Notes & software courses · Free to learn
Aph's Blog
On this page

Dictionary — คู่ key-value ที่ค้นหาเร็ว

👋 อ่านฟรีทั้งหมดบน Aph's Blog — เนื้อหาภาษาไทย ทำตามทีละหน้าใน sidebar ได้เลย หากมีข้อเสนอแนะหรืออยากให้เพิ่มหัวข้อไหน บอกได้เสมอ

เก็บข้อมูลเป็นคู่ "กุญแจ → ค่า" เข้าถึงด้วย key ค้นหาเร็วระดับ O(1) — หนึ่งในโครงสร้างที่ทรงพลังที่สุด

Dictionary (dict) เก็บข้อมูลเป็นคู่ "key → value" เหมือนพจนานุกรมที่เปิดหาคำ (key) แล้วได้ความหมาย (value) ต่างจากลิสต์ที่เข้าถึงด้วยตำแหน่ง dict เข้าถึงด้วย key ที่สื่อความหมาย และค้นหาเร็วมาก (เฉลี่ย O(1)) เป็นโครงสร้างที่ใช้บ่อยรองจากลิสต์

สร้างและเข้าถึง

python
student = {
    "name": "Aphisit",
    "age": 25,
    "gpa": 3.5,
}
print(student["name"])    # Aphisit  (เข้าถึงด้วย key)
print(student["gpa"])     # 3.5

student["age"] = 26       # แก้ค่า
student["city"] = "Bangkok"  # เพิ่มคู่ใหม่
del student["gpa"]        # ลบคู่
print(student)
ระวัง KeyError

เข้าถึง key ที่ไม่มีจะ error เช่น student["phone"] ได้ KeyError ใช้ .get() ปลอดภัยกว่า: student.get("phone") คืน None ถ้าไม่มี หรือ student.get("phone", "ไม่มีข้อมูล") กำหนดค่าสำรองได้

เมธอดและการเช็ค key

python
d = {"a": 1, "b": 2, "c": 3}

print("a" in d)         # True   เช็คว่ามี key นี้ไหม
print(d.get("z", 0))    # 0      ดึงค่าแบบปลอดภัย
print(d.keys())         # dict_keys(['a','b','c'])
print(d.values())       # dict_values([1, 2, 3])
print(d.items())        # คู่ (key, value) ทั้งหมด
print(len(d))           # 3

วน loop ใน dictionary

python
scores = {"Aphisit": 80, "Mali": 92, "Mochi": 75}

for name in scores:                  # วนได้ key โดยตรง
    print(name)

for name, score in scores.items():   # วนทั้ง key และ value
    print(f"{name} ได้ {score} คะแนน")

# หาคนที่คะแนนเกิน 80
for name, score in scores.items():
    if score > 80:
        print(f"{name} ผ่านเกณฑ์")

ใช้งานยอดฮิต: นับความถี่ (Counting)

หนึ่งในการใช้ dict ที่เจอบ่อยที่สุดในข้อสอบคือ "นับจำนวน" เช่นนับว่าตัวอักษร/คำแต่ละตัวปรากฏกี่ครั้ง เพราะ dict ค้นหาเร็ว จึงทำได้ใน O(n)

python
text = "banana"
count = {}
for ch in text:
    count[ch] = count.get(ch, 0) + 1  # ไม่มี key ให้เริ่มที่ 0
print(count)   # {'b': 1, 'a': 3, 'n': 2}

# มีเครื่องมือสำเร็จรูปด้วย
from collections import Counter
print(Counter("banana"))  # Counter({'a': 3, 'n': 2, 'b': 1})
ทำไม dict สำคัญในข้อสอบ

โจทย์ประเภท "นับ", "จับคู่", "เคยเห็นค่านี้มาก่อนไหม" มักแก้เร็วด้วย dict แทนที่จะวนหาทั้งลิสต์ (O(n) ต่อครั้ง) การเช็คใน dict เร็วระดับ O(1) ทำให้อัลกอริทึมโดยรวมเร็วขึ้นมาก (จะเห็นชัดในบท Big-O)

จัดกลุ่มข้อมูล (Grouping) — แพตเทิร์นที่เจอบ่อย

อีกการใช้ dict ยอดฮิตคือ "จัดกลุ่ม" — เก็บลิสต์ของสมาชิกแยกตามกลุ่ม เช่นจัดนักเรียนตามเกรด หรือคำตามตัวอักษรแรก

python
students = [("Aph", "A"), ("Bee", "B"), ("Cha", "A")]

groups = {}
for name, grade in students:
    if grade not in groups:
        groups[grade] = []        # ยังไม่มีกลุ่มนี้ สร้างลิสต์ว่าง
    groups[grade].append(name)
print(groups)   # {'A': ['Aph', 'Cha'], 'B': ['Bee']}

# มีเครื่องมือสำเร็จที่สั้นกว่า
from collections import defaultdict
groups = defaultdict(list)        # ค่า default ของ key ใหม่ = ลิสต์ว่าง
for name, grade in students:
    groups[grade].append(name)    # ไม่ต้องเช็คว่ามี key ไหม

dict ซ้อนกัน (Nested)

python
users = {
    "u1": {"name": "Aphisit", "age": 25},
    "u2": {"name": "Mali", "age": 22},
}
print(users["u1"]["name"])   # Aphisit

for uid, info in users.items():
    print(f"{uid}: {info['name']} อายุ {info['age']}")

สรุปหัวข้อนี้

  • dict เก็บคู่ key → value เข้าถึงด้วย key ที่สื่อความหมาย
  • ค้นหา/เพิ่ม/แก้/ลบ เร็วเฉลี่ย O(1)
  • ใช้ .get(key, default) เลี่ยง KeyError
  • วนด้วย .items() เพื่อได้ทั้ง key และ value
  • ใช้งานยอดฮิต: นับความถี่ (Counter) และจัดกลุ่ม (grouping/defaultdict)
  • dict ซ้อนกันได้ ใช้แทนข้อมูลที่มีโครงสร้างซับซ้อน (คล้าย JSON)
แบบฝึกหัด

1) สร้าง dict เก็บชื่อ-คะแนนนักเรียน แล้ว print คนที่คะแนนเกิน 50 2) นับความถี่ของตัวอักษรในคำที่รับมา 3) นับความถี่ของคำในประโยค (split ก่อน) 4) สร้างสมุดโทรศัพท์ที่เพิ่ม/ค้นหา/ลบรายชื่อได้ด้วยเมนู (ใช้ while loop) 5) หา key ที่มี value มากที่สุดใน dict