Python เซ็ต (Set)



เซ็ต (Set) คือคอลเลกชันที่เก็บสมาชิกโดย ไม่อนุญาตให้มีค่าซ้ำกัน และ ไม่ให้ความสำคัญกับลำดับของสมาชิก

เซ็ตจึงเหมาะกับงานที่ต้องการเก็บข้อมูลแบบไม่ซ้ำ เช่น การหาว่า “มีอะไรบ้างโดยไม่นับค่าซ้ำ” หรือการตรวจสอบว่า “มีค่านี้อยู่ในกลุ่มหรือไม่”

สร้างเซ็ต

ใช้ปีกกา {} คั่นสมาชิกด้วยจุลภาค

colors = {"แดง", "เขียว", "น้ำเงิน"}
numbers = {1, 2, 3, 4, 5}

ถ้าใส่ค่าซ้ำเข้าไป Python ตัดทิ้งให้เอง

nums = {1, 2, 2, 3, 3, 3}
print(nums)   # {1, 2, 3}

หมายเหตุ: ลำดับสมาชิกที่แสดงในตัวอย่างอาจแตกต่างกันได้ เนื่องจากเซ็ตไม่รับประกันลำดับของสมาชิก

ระวัง: เซ็ตว่างต้องใช้ set() ไม่ใช่ {} เพราะ {} คือ dict ว่าง

empty_set = set()
empty_dict = {}

กรองค่าซ้ำออกจากลิสต์

นี่คือการใช้งานที่พบบ่อยที่สุด เอาลิสต์แปลงเป็นเซ็ต ค่าซ้ำหายไปเอง แล้วแปลงกลับเป็นลิสต์

names = ["สมชาย", "สมหญิง", "สมชาย", "สมศรี", "สมหญิง"]

unique = list(set(names))
print(unique)   # ['สมหญิง', 'สมชาย', 'สมศรี']  (ลำดับไม่แน่นอน)
print(len(set(names)))   # 3  จำนวนคนที่ไม่ซ้ำ

ข้อแลกเปลี่ยนคือ ลำดับเดิมหาย ถ้าต้องรักษาลำดับด้วย ใช้ dict.fromkeys() แทน

unique_ordered = list(dict.fromkeys(names))
print(unique_ordered)   # ['สมชาย', 'สมหญิง', 'สมศรี']

เพิ่มและลบสมาชิก

colors = {"แดง", "เขียว"}

colors.add("น้ำเงิน")
print(colors)   # {'แดง', 'เขียว', 'น้ำเงิน'}

colors.discard("เขียว")     # ถ้าไม่มีค่านี้ จะไม่เกิด error
colors.remove("แดง")       # ถ้าไม่มีค่านี้ จะเกิด KeyError
print(colors)   # {'น้ำเงิน'}

เช็คสมาชิก

โดยทั่วไป การตรวจสอบสมาชิกด้วย in ในเซ็ตทำได้เร็วกว่าลิสต์ โดยเฉพาะเมื่อมีข้อมูลจำนวนมาก

ถ้าต้องตรวจสอบว่า “มีค่านี้อยู่หรือไม่” บ่อย ๆ การเก็บข้อมูลเป็นเซ็ตจึงเป็นตัวเลือกที่เหมาะสม

allowed_users = {"admin", "editor", "author"}

user = "editor"
if user in allowed_users:
    print("มีสิทธิ์เข้าถึง")

ถ้าคุณมีข้อมูลก้อนใหญ่ที่ต้องเช็ค “มีอยู่ไหม” บ่อย ๆ เก็บเป็นเซ็ตจะได้ประสิทธิภาพดีกว่าลิสต์มาก

การดำเนินการแบบเซ็ต

ตรงนี้คือจุดที่เซ็ตทำได้ดีกว่าคอลเลกชันอื่น เหมือนวิชาเซ็ตที่เรียนสมัยมัธยม

a = {1, 2, 3, 4}
b = {3, 4, 5, 6}

Union (รวม) — อยู่ใน a หรือ b

print(a | b)          # {1, 2, 3, 4, 5, 6}
print(a.union(b))     # {1, 2, 3, 4, 5, 6} เหมือนกัน

Intersection (ร่วม) — อยู่ทั้งใน a และ b

print(a & b)                 # {3, 4}
print(a.intersection(b))     # {3, 4} เหมือนกัน

Difference (ผลต่าง) — อยู่ใน a แต่ไม่อยู่ใน b

print(a - b)               # {1, 2}
print(a.difference(b))     # {1, 2} เหมือนกัน

Symmetric difference (ผลต่างแบบสมมาตร) — อยู่ใน a หรือ b แต่ไม่อยู่ในทั้งสองเซ็ตพร้อมกัน

print(a ^ b)   # {1, 2, 5, 6}

Subset/Superset — Subset ใช้ตรวจว่าสมาชิกทั้งหมดของเซ็ตหนึ่งอยู่ในอีกเซ็ตหรือไม่ ส่วน Superset คือการตรวจในทิศทางตรงกันข้าม

a = {1, 2}
b = {1, 2, 3, 4}

print(a <= b)   # True  a เป็น subset ของ b
print(b >= a)   # True  b เป็น superset ของ a

ตัวอย่างจริง: หาแท็กที่ทั้งสองบทความใช้ร่วมกัน

tags_a = {"python", "beginner", "tutorial", "loop"}
tags_b = {"python", "list", "tutorial", "data"}

common = tags_a & tags_b
only_a = tags_a - tags_b

print("ใช้ร่วมกัน:", common)         # {'python', 'tutorial'}
print("เฉพาะบทความ A:", only_a)   # {'beginner', 'loop'}

ตัวอย่างจริง: เช็คคำตอบว่าครบไหม

required = {"ชื่อ", "อีเมล", "เบอร์โทร"}
submitted = {"ชื่อ", "อีเมล"}

missing = required - submitted
if missing:
    print("ยังกรอกไม่ครบ:", missing)   # {'เบอร์โทร'}
else:
    print("ข้อมูลครบแล้ว")

ข้อจำกัด

  • เซ็ตสามารถเก็บค่าอย่างตัวเลข (int), ข้อความ (str) และ tuple ที่มีสมาชิกเหมาะสมได้ แต่ไม่สามารถนำ list, dict หรือ set มาเป็นสมาชิกของเซ็ตโดยตรงได้
  • เซ็ตไม่มี index จะเขียน myset[0] ไม่ได้ ถ้าต้องการลำดับให้ใช้ลิสต์
  • ลำดับสมาชิกไม่แน่นอน อย่าพึ่งพาว่าจะเรียงแบบไหน

สรุป

  • เซ็ตเก็บข้อมูลไม่ซ้ำ ไม่สนลำดับ สร้างด้วย {} (แต่เซ็ตว่างใช้ set())
  • list(set(x)) กรองค่าซ้ำได้ทันที แต่ลำดับหาย
  • in กับเซ็ตเร็วกว่าลิสต์มากเมื่อข้อมูลเยอะ
  • | รวม, & ร่วม, - ผลต่าง, ^ ต่างแบบสมมาตร, <= subset และ >= superset

บทถัดไปเป็นดิกชันนารี (Dictionary) โครงสร้างข้อมูลแบบคู่ คีย์–ค่า ที่ใช้บ่อยที่สุดตัวหนึ่งใน Python