BAB 17: Set

Pelajari set sebagai tipe data kolektif yang menjamin keunikan elemen — tidak ada duplikat, dan operasi himpunan matematika bisa langsung dipakai.

List dan tuple yang sudah kita pelajari di tiga bab terakhir punya satu kesamaan: keduanya memperbolehkan elemen duplikat. Kamu bisa menyimpan "Rina" lima kali di list tanpa Python memberi peringatan apapun. Untuk banyak kasus itu tidak masalah — daftar kehadiran harian memang bisa mencatat nama yang sama berulang kali. Tapi ada situasi di mana duplikasi justru menjadi masalah: daftar peserta kuis yang seharusnya unik, kumpulan tag yang tidak boleh berulang, atau daftar mata pelajaran yang tersedia.

Python punya tipe data kolektif yang secara otomatis menjamin keunikan setiap elemennya: set. Tidak peduli berapa kali kamu memasukkan nilai yang sama, set hanya menyimpan satu salinan.

Membuat Set

Set dibuat dengan kurung kurawal {} — mirip dictionary yang nanti akan kita pelajari, tapi tanpa pasangan key-value.

# kuis.py — daftar mata pelajaran yang tersedia (unik)
mapel_tersedia = {"Matematika", "Fisika", "Kimia", "Biologi"}
print(mapel_tersedia)
print(type(mapel_tersedia))
{'Kimia', 'Biologi', 'Fisika', 'Matematika'}
<class 'set'>

Perhatikan bahwa urutan elemen saat dicetak tidak sama dengan urutan saat ditulis. Ini bukan bug — set memang tidak terurut (unordered). Berbeda dari list dan tuple yang menyimpan elemen sesuai posisi, set tidak punya konsep index. Kamu tidak bisa menulis mapel_tersedia[0] — Python akan melempar TypeError.

Set Menolak Duplikat

Coba masukkan elemen yang sama lebih dari sekali:

# kuis.py — duplikat otomatis dihapus
peserta = {"Rina", "Budi", "Sari", "Rina", "Budi"}
print(peserta)
print(f"Jumlah peserta: {len(peserta)}")
{'Budi', 'Sari', 'Rina'}
Jumlah peserta: 3

Dari lima elemen yang dimasukkan, hanya tiga yang tersimpan. Python secara otomatis membuang duplikat tanpa peringatan apapun — itulah perilaku fundamental set.

Set Kosong

Ada satu jebakan penting: kurung kurawal kosong {} bukan set kosong, melainkan dictionary kosong. Untuk membuat set kosong, gunakan fungsi set().

# kuis.py — hati-hati dengan {} kosong
bukan_set = {}
set_asli = set()

print(type(bukan_set))
print(type(set_asli))
<class 'dict'>
<class 'set'>

Ini salah satu inkonsistensi kecil di Python yang perlu diingat. Begitu set sudah berisi elemen, kurung kurawal bekerja sesuai harapan — masalah hanya muncul saat set kosong.

Membuat Set dari Tipe Lain

Fungsi set() juga bisa mengonversi list, tuple, string, atau range() menjadi set — dan secara otomatis menghilangkan duplikat dalam prosesnya.

# kuis.py — konversi dari tipe lain
skor_list = [85, 72, 91, 85, 68, 72]
skor_unik = set(skor_list)
print(skor_unik)

# dari string — setiap karakter jadi elemen
huruf = set("MATEMATIKA")
print(huruf)

# dari range
angka = set(range(1, 6))
print(angka)
{68, 72, 85, 91}
{'M', 'K', 'I', 'T', 'A', 'E'}
{1, 2, 3, 4, 5}

Konversi dari list ke set adalah salah satu cara paling cepat untuk menghilangkan duplikat dari data. Ingat ketika kita bekerja dengan list di BAB 14 dan harus menulis loop manual untuk mencari elemen unik? Set menyelesaikan masalah itu dalam satu baris.

Menambah dan Menghapus Elemen

Set bersifat mutable — sama seperti list, kamu bisa menambah dan menghapus elemen setelah set dibuat. Bedanya, set tidak punya konsep posisi, jadi tidak ada insert() atau append() yang menempatkan elemen di index tertentu.

Menambah Elemen

Method add() memasukkan satu elemen ke set. Jika elemen sudah ada, tidak terjadi apa-apa.

# kuis.py — mendaftarkan peserta baru
peserta = {"Rina", "Budi", "Sari"}
print(f"Sebelum: {peserta}")

peserta.add("Dimas")
peserta.add("Rina")  # sudah ada, diabaikan
print(f"Sesudah: {peserta}")
Sebelum: {'Budi', 'Sari', 'Rina'}
Sesudah: {'Budi', 'Dimas', 'Sari', 'Rina'}

"Rina" sudah ada di set, jadi pemanggilan add("Rina") kedua tidak menghasilkan duplikat. Ini berbeda dari list.append() yang selalu menambahkan tanpa peduli apakah elemen sudah ada.

Menghapus Elemen

Ada tiga cara menghapus elemen dari set, dan perbedaannya terletak pada bagaimana mereka menangani elemen yang tidak ditemukan:

# kuis.py — tiga cara menghapus elemen
peserta = {"Rina", "Budi", "Sari", "Dimas"}

# discard() — aman, tidak error jika elemen tidak ada
peserta.discard("Budi")
peserta.discard("Fajar")  # tidak ada, tapi tidak error
print(f"Setelah discard: {peserta}")

# remove() — error jika elemen tidak ada
peserta.remove("Sari")
print(f"Setelah remove: {peserta}")

# pop() — hapus dan kembalikan elemen acak
dihapus = peserta.pop()
print(f"Elemen yang di-pop: {dihapus}")
print(f"Sisa: {peserta}")
Setelah discard: {'Dimas', 'Sari', 'Rina'}
Setelah remove: {'Dimas', 'Rina'}
Elemen yang di-pop: Dimas
Sisa: {'Rina'}

Perbandingan ketiga method ini:

MethodElemen tidak ditemukanMengembalikan nilai
discard()Diam saja, tidak errorTidak
remove()Melempar KeyErrorTidak
pop()Melempar KeyError jika set kosongYa, elemen yang dihapus

Gunakan discard() sebagai pilihan default saat menghapus elemen dari set. Method ini lebih aman karena tidak memaksa kamu menulis pengecekan if elemen in set sebelum menghapus.

Untuk mengosongkan seluruh set sekaligus, gunakan clear():

# kuis.py
peserta = {"Rina", "Budi", "Sari"}
peserta.clear()
print(peserta)
set()

Iterasi Set

Meskipun set tidak punya index, kamu tetap bisa melakukan iterasi dengan for — sama seperti list dan tuple:

# kuis.py — cetak semua mata pelajaran
mapel = {"Matematika", "Fisika", "Kimia", "Biologi"}

for m in mapel:
    print(f"- {m}")
- Kimia
- Biologi
- Fisika
- Matematika

Urutan iterasi tidak bisa diprediksi — jangan bergantung pada urutan elemen di set. Jika urutan penting, konversi dulu ke list lalu urutkan:

# kuis.py — iterasi terurut
mapel = {"Matematika", "Fisika", "Kimia", "Biologi"}

for m in sorted(mapel):
    print(f"- {m}")
- Biologi
- Fisika
- Kimia
- Matematika

Fungsi sorted() yang kita kenal dari BAB 14 mengembalikan list baru yang terurut — set asli tidak berubah.

Operasi Himpunan

Di sinilah kekuatan utama set yang tidak dimiliki list maupun tuple. Set mendukung operasi himpunan matematika yang sudah kamu pelajari di bangku sekolah: gabungan, irisan, selisih, dan selisih simetris.

Bayangkan skenario kuis di mana kita ingin menganalisis peserta dari dua sesi yang berbeda:

# kuis.py — peserta dua sesi kuis
sesi_pagi = {"Rina", "Budi", "Sari", "Dimas"}
sesi_siang = {"Sari", "Dimas", "Lina", "Fajar"}

Union — Gabungan

Menggabungkan semua elemen dari kedua set, tanpa duplikat:

# kuis.py
semua_peserta = sesi_pagi | sesi_siang
# atau: semua_peserta = sesi_pagi.union(sesi_siang)

print(f"Semua peserta: {semua_peserta}")
print(f"Total: {len(semua_peserta)}")
Semua peserta: {'Dimas', 'Lina', 'Rina', 'Fajar', 'Budi', 'Sari'}
Total: 6

Meskipun "Sari" dan "Dimas" ada di kedua sesi, mereka hanya muncul sekali di hasil union.

Intersection — Irisan

Mengambil elemen yang ada di kedua set:

# kuis.py
ikut_dua_sesi = sesi_pagi & sesi_siang
# atau: ikut_dua_sesi = sesi_pagi.intersection(sesi_siang)

print(f"Ikut dua sesi: {ikut_dua_sesi}")
Ikut dua sesi: {'Sari', 'Dimas'}

Difference — Selisih

Mengambil elemen yang ada di set pertama tapi tidak ada di set kedua:

# kuis.py
hanya_pagi = sesi_pagi - sesi_siang
# atau: hanya_pagi = sesi_pagi.difference(sesi_siang)

hanya_siang = sesi_siang - sesi_pagi

print(f"Hanya sesi pagi: {hanya_pagi}")
print(f"Hanya sesi siang: {hanya_siang}")
Hanya sesi pagi: {'Rina', 'Budi'}
Hanya sesi siang: {'Lina', 'Fajar'}

Perhatikan bahwa urutan operand berpengaruh: sesi_pagi - sesi_siang dan sesi_siang - sesi_pagi menghasilkan set yang berbeda.

Symmetric Difference — Selisih Simetris

Mengambil elemen yang ada di salah satu set, tapi tidak di keduanya:

# kuis.py
hanya_satu_sesi = sesi_pagi ^ sesi_siang
# atau: hanya_satu_sesi = sesi_pagi.symmetric_difference(sesi_siang)

print(f"Hanya ikut satu sesi: {hanya_satu_sesi}")
Hanya ikut satu sesi: {'Rina', 'Budi', 'Lina', 'Fajar'}

Ringkasan operator dan method-nya:

OperatorMethodHasil
|union()Semua elemen dari kedua set
&intersection()Elemen yang ada di kedua set
-difference()Elemen di set pertama, bukan di set kedua
^symmetric_difference()Elemen yang hanya di salah satu set

Relasi Antar Set

Selain operasi yang menghasilkan set baru, Python juga menyediakan method untuk mengecek hubungan antara dua set:

# kuis.py — cek relasi antar set
mapel_kuis = {"Matematika", "Fisika", "Kimia"}
mapel_lengkap = {"Matematika", "Fisika", "Kimia", "Biologi", "Geografi"}
mapel_olahraga = {"Basket", "Voli"}

# subset — apakah semua elemen ada di set lain?
print(mapel_kuis.issubset(mapel_lengkap))

# superset — apakah set ini memuat seluruh elemen set lain?
print(mapel_lengkap.issuperset(mapel_kuis))

# disjoint — apakah kedua set tidak punya elemen yang sama?
print(mapel_kuis.isdisjoint(mapel_olahraga))
print(mapel_kuis.isdisjoint(mapel_lengkap))
True
True
True
False

mapel_kuis adalah subset dari mapel_lengkap karena semua elemennya (Matematika, Fisika, Kimia) juga ada di mapel_lengkap. Sebaliknya, mapel_lengkap adalah superset dari mapel_kuis. Sedangkan mapel_kuis dan mapel_olahraga bersifat disjoint — tidak ada elemen yang sama di antara keduanya.

Set Comprehension

Ingat list comprehension dari BAB 15? Set punya padanan yang sama persis, hanya saja menggunakan kurung kurawal alih-alih kurung siku:

# kuis.py — buat set dari list dengan filter
semua_skor = [85, 72, 91, 68, 77, 91, 85, 72, 64, 88]

# ambil skor unik yang di atas rata-rata
rata_rata = sum(semua_skor) / len(semua_skor)
skor_tinggi = {s for s in semua_skor if s > rata_rata}

print(f"Rata-rata: {rata_rata}")
print(f"Skor di atas rata-rata (unik): {skor_tinggi}")
Rata-rata: 79.3
Skor di atas rata-rata (unik): {88, 85, 91}

Set comprehension menggabungkan dua keunggulan: filtering dari comprehension dan keunikan dari set. Hasilnya langsung bersih dari duplikat tanpa langkah tambahan.

Frozenset — Set yang Immutable

Hubungan antara list dan tuple sudah kita pahami: list bersifat mutable, tuple adalah versi immutable-nya. Set punya pasangan serupa: frozenset.

# kuis.py — frozenset tidak bisa diubah
mapel_wajib = frozenset({"Matematika", "Fisika", "Kimia"})
print(mapel_wajib)
print(type(mapel_wajib))
frozenset({'Kimia', 'Fisika', 'Matematika'})
<class 'frozenset'>

Frozenset mendukung semua operasi yang tidak mengubah set — union(), intersection(), difference(), issubset(), dan lainnya tetap bekerja. Tapi method yang mengubah isi seperti add(), remove(), dan discard() tidak tersedia:

# kuis.py — ini akan error
mapel_wajib = frozenset({"Matematika", "Fisika", "Kimia"})
mapel_wajib.add("Biologi")
AttributeError: 'frozenset' object has no attribute 'add'

Frozenset berguna ketika kamu butuh set sebagai elemen dari set lain, atau sebagai key dictionary — sesuatu yang tidak bisa dilakukan dengan set biasa karena set bersifat mutable dan tidak hashable. Konsep hashable ini akan lebih jelas saat kita membahas dictionary.

Kapan Pakai Set

Setelah mempelajari list, tuple, dan sekarang set, kamu punya tiga tipe data kolektif dengan karakteristik berbeda:

FiturListTupleSet
TerurutYaYaTidak
MutableYaTidakYa
DuplikatDiizinkanDiizinkanOtomatis dihapus
Akses indexYaYaTidak
Kasus pakai utamaKoleksi umumData tetapData unik

Pedoman memilih:

  • List — koleksi yang berubah-ubah dan urutan penting: daftar peserta, antrian tugas, skor yang bisa dikoreksi.
  • Tuple — data yang tidak boleh berubah dan posisi bermakna: koordinat, konfigurasi tetap, return value fungsi.
  • Set — kumpulan elemen yang harus unik dan urutan tidak penting: tag, kategori, daftar hak akses, ID yang sudah diproses.

Satu keunggulan teknis set yang belum kita bahas: pengecekan keanggotaan (in) pada set jauh lebih cepat dibanding list. Untuk list dengan ribuan elemen, Python harus memeriksa satu per satu dari awal. Set menggunakan mekanisme internal yang memungkinkan pengecekan langsung tanpa iterasi. Jika kamu sering mengecek apakah suatu elemen ada di koleksi, set adalah pilihan yang lebih tepat.

Latihan

Tiga tantangan ini menggabungkan set dengan konsep dari bab-bab sebelumnya:

  1. Kamu punya dua list peserta kuis dari hari yang berbeda: hari_senin = ["Rina", "Budi", "Sari", "Dimas"] dan hari_rabu = ["Sari", "Lina", "Dimas", "Fajar"]. Gunakan operasi set untuk menemukan: peserta yang ikut di kedua hari, peserta yang hanya ikut hari Senin, dan total peserta unik. Cetak hasilnya.

  2. Buat list skor_mentah = [85, 72, 91, 68, 77, 91, 85, 72, 64, 88, 77, 85]. Tanpa menggunakan loop, temukan berapa banyak skor unik yang ada. Kemudian, gunakan set comprehension untuk membuat set berisi skor unik yang nilainya di atas 75.

  3. Buat dua frozenset: mapel_ipa = frozenset({"Fisika", "Kimia", "Biologi"}) dan mapel_wajib = frozenset({"Matematika", "Fisika", "Kimia"}). Tanpa mengubah kedua frozenset, temukan mata pelajaran yang masuk kategori IPA tapi bukan wajib, dan mata pelajaran wajib yang bukan IPA. Buktikan bahwa frozenset bisa menjadi elemen dari set biasa dengan memasukkan keduanya ke dalam satu set.

Tiga tipe data kolektif sudah kita kuasai — list untuk data yang fleksibel, tuple untuk data yang terkunci, dan set untuk data yang unik. Tapi ketiganya punya satu keterbatasan yang sama: untuk mengakses elemen, kita harus tahu posisinya (list dan tuple) atau mengiterasi seluruh isinya (set). Bagaimana kalau kita bisa mengakses data berdasarkan label yang bermakna — misalnya data["nama"] alih-alih data[0]?

Referensi

  1. 1Python Docs — Set Types: set, frozenset
  2. 2Python Tutorial — Sets
  3. 3Real Python — Sets in Python