Belajar dengan membaca secara berurutan

collections — Counter / defaultdict / deque / namedtuple

Pelajari Counter untuk hitung kemunculan, defaultdict untuk key hilang, operasi O(1) dua ujung dan ring buffer deque, serta record bernama namedtuple lewat contoh.

Modul collections mengumpulkan struktur data khusus yang mengisi celah yang ditinggalkan oleh list / dict / tuple. Artikel ini membahas empat yang paling sering kamu pakai di proyek nyata: Counter / defaultdict / deque / namedtuple, secara berurutan.

Untuk apa masing-masing dari empat ini

Setiap satu hadir untuk menyederhanakan kasus yang canggung kalau ditulis dengan built-in biasa. Tabel di bawah memberi kamu pandangan menyeluruh, lalu setiap bagian membahas cara memakainya.

Empat tipe collections
CounterHitung kemunculandefaultdictAuto-init key hilangdequeO(1) di kedua ujungnamedtupleBeri nama field tuple
Counter untuk penghitungan, defaultdict menangani key yang hilang, deque memberi operasi cepat di kedua ujung, dan namedtuple menambahkan nama ke tuple. Keempatnya adalah tipe ekstensi yang menambah kenyamanan di atas list / dict / tuple biasa.
TipeMasalah yang diselesaikanAlternatif biasa
CounterMenghitung elemen satu per satu dengan loop terlalu panjangfor + dict tally
defaultdictPerlu if x not in d: d[x] = ... sebelum memakai key barudict.setdefault(...)
dequelist.insert(0, ...) dan list.pop(0) lambat (O(n))list (cukup untuk data kecil)
namedtupleElemen tuple hanya bisa diakses lewat posisidataclass atau dict (lebih berat)

Counter — hitung kemunculan dalam satu baris

Counter adalah class yang menerima iterable (list, string, dll.) dan mengembalikan dict berisi berapa kali setiap elemen muncul. Dengan dict biasa, kamu harus menulis loop yang memeriksa apakah key sudah ada, menginisialisasinya ke 1 jika belum, atau menambahkannya jika sudah — tetapi Counter menyelesaikan pekerjaan yang sama dalam satu baris: Counter(list).

Nilai kembaliannya adalah subclass dari dict, jadi kamu bisa mengambil nilai dengan counter["apple"] seperti dict biasa. Ada juga .most_common(N), yang mengembalikan list tuple (elemen, count) dalam urutan menurun — pas untuk tampilan ranking.

Cara kerja Counter
List[apple, banana, apple, ...]Counter(list)Counter{apple: 3, banana: 2, ...}tally
Cukup teruskan iterable dan kamu mendapatkan subclass dict berisi count kemunculan per elemen. most_common(N) mengembalikan top N berdasarkan frekuensi, jadi kamu bisa menulis tampilan ranking dalam satu baris.

Hitung enam catatan pembelian per produk dengan Counter. Rasakan bagaimana satu baris menggantikan loop for biasa.

① Impor Counter dari collections

② Definisikan list pembelian ["apple", "banana", "apple", "cherry", "banana", "apple"]

③ Teruskan list ke Counter untuk membangun tally dan cetak sebagai Jumlah: ◯

④ Cetak jumlah apple sebagai jumlah apple: ◯ (kamu bisa pakai akses kurung siku yang sama seperti dict)

⑤ Pakai most_common untuk mengambil top 2 dan cetak sebagai Top 2: ◯

(Jika kode kamu jalan dengan benar, penjelasannya akan muncul.)

Python Editor

Jalankan kode untuk melihat output

defaultdict — auto-inisialisasi key yang hilang

defaultdict adalah dict yang otomatis menyisipkan nilai default ketika kamu mengakses key yang belum ada. Dengan dict biasa, kamu harus menulis tarian pemeriksaan keberadaan + inisialisasi setiap kali, seperti if key not in d: d[key] = []. Dengan defaultdict, kamu meneruskan fungsi yang menghasilkan nilai awal saat membuatnya, dan ia memanggil fungsi itu otomatis pertama kali key yang hilang disentuh.

Dua pola yang paling sering kamu lihat adalah defaultdict(list) (list kosong untuk key yang hilang) dan defaultdict(int) (0 untuk key yang hilang). Argumennya adalah fungsi yang mengembalikan nilai awal ketika dipanggil tanpa argumenlist dan int keduanya memenuhi (mereka mengembalikan [] dan 0 masing-masing), jadi kamu meneruskannya langsung.

dict vs. defaultdict
dict biasad["x"] (tidak ada key)→ KeyErrorPerlu:if x not in d: d[x] = []defaultdict(list)d["x"] (tidak ada key)→ Auto-buat []Cukup panggil .append(...)langsung
dict biasa melempar KeyError pada key yang hilang. defaultdict memanggil fungsi yang kamu teruskan saat konstruksi dan memakai hasilnya. Teruskan list untuk list kosong, int untuk 0, set untuk set kosong.

Kapan memilih Counter vs. defaultdict

Jika kamu hanya ingin menghitung sesuatu, Counter lebih ringkas (dan kamu mendapatkan most_common secara gratis). Jika kamu mengelompokkan ke list atau set — apa pun yang nilai awalnya container kosongdefaultdict(list) / defaultdict(set) lebih cocok.

Kelompokkan buah berdasarkan warna. Dengan defaultdict(list), pertama kali kamu menyentuh key warna, ia auto-membuat list kosong, jadi kamu bisa memanggil .append tanpa pemeriksaan keberadaan.

① Impor defaultdict dari collections

② Buat defaultdict yang nilai default-nya adalah list kosong

③ Daftarkan tiga entri ini secara berurutan:

- "red""apple"

- "yellow""banana"

- "red""cherry"

Konversi ke dict biasa dan cetak sebagai Per warna: ◯ (mencetak defaultdict langsung memberi repr yang kurang mudah dibaca)

Python Editor

Jalankan kode untuk melihat output

deque — operasi O(1) di kedua ujung

deque (double-ended queue) adalah struktur data mirip list yang mendukung penambahan dan penghapusan dari kedua ujung. list biasa sudah menangani operasi ujung kanan via append dan pop, tetapi list.insert(0, x) dan list.pop(0) menggeser setiap elemen satu slot di belakang layar, jadi mereka berakhir O(n) (lebih lambat saat list bertambah).

deque dirancang sehingga kedua ujungnya O(1) (waktu konstan terlepas dari panjang), menjadikannya pilihan tepat untuk antrian, buffer histori, dan menyimpan N entri terbaru — di mana pun kamu perlu push dan pop dari kedua sisi. Argumen maxlen sangat berguna: set panjang maksimum, dan penambahan melampaui batas itu diam-diam menjatuhkan elemen di ujung berlawanan, memberi kamu ring buffer secara gratis.

biaya operasi list vs. deque
listTambah / hapus ujung kiriGeser setiap elemensatu slot→ O(n) lambatdequeappend / pop kedua ujungHanya manipulasipointer→ O(1) cepat
Operasi ujung kiri list adalah O(n) (setiap elemen bergeser), sementara deque adalah O(1) di kedua ujung. Dengan deque(maxlen=N), kamu mendapatkan ring buffer yang otomatis menjatuhkan yang tertua saat penuh.
MethodEfekBiaya
append(x)Tambah ke ujung kananO(1)
appendleft(x)Tambah ke ujung kiriO(1)
pop()Hapus dari ujung kananO(1)
popleft()Hapus dari ujung kiriO(1)
maxlen=NSet panjang maksimum (ring buffer)Ujung berlawanan dijatuhkan otomatis
method utama deque
appendleft(x)deque[a, b, c]append(x)popleft()pop()
Terhadap deque pusat, ujung kiri pakai appendleft / popleft dan ujung kanan pakai append / pop. Arah panah menunjukkan tambah (masuk ke deque) vs. hapus (keluar dari deque).

Simpan 3 log akses terakhir di deque(maxlen=3). Setelah 5 append, hanya 3 terakhir yang bertahan.

① Impor deque dari collections

② Buat deque kosong dengan panjang maksimum 3

Tambahkan integer 0 sampai 4 secara berurutan (5 total)

④ Cetak hasilnya sebagai 3 terakhir: ◯ (0 dan 1 yang lebih lama seharusnya sudah terdorong keluar)

Python Editor

Jalankan kode untuk melihat output

Pop kepala dan ekor antrian tugas. Pakai popleft dan pop untuk berganti dari ujung mana kamu mengambil.

① Impor deque dari collections

② Bangun deque dari empat tugas ["Tugas A", "Tugas B", "Tugas C", "Tugas D"]

③ Pakai popleft() untuk mengambil tugas pertama dan cetak sebagai Tugas pertama: ◯

④ Pakai pop() untuk mengambil tugas terakhir dan cetak sebagai Tugas terakhir: ◯

⑤ Cetak deque yang tersisa sebagai Sisa: ◯

Python Editor

Jalankan kode untuk melihat output

namedtuple — record ringan yang menamai field tuple

namedtuple adalah fungsi yang mendefinisikan tuple bernama dalam satu baris. Tuple biasa seperti (3, 4) hanya bisa diakses lewat posisi (p[0] / p[1]), jadi pembaca harus mengingat slot mana yang mana. namedtuple membiarkan kamu menulis p.x / p.y dengan nama bermakna, yang merupakan kemenangan keterbacaan besar.

Ia juga tetap kompatibel dengan tuple biasa — indexing p[0] dan unpacking *p masih bekerja — jadi kamu bisa menambahkan nama ke kode berbasis tuple yang sudah ada tanpa merusak apa pun. Ini ekstensi ringan.

namedtuple sekilas
Point = namedtuple('Point', ['x', 'y'])p = Point(3, 4)Per namap.x / p.yPer indeksp[0] / p[1]Sebagai dictp._asdict()
Definisikan setara class dalam satu baris, lalu pakai akses posisional (p[0]) dan akses bernama (p.x). _asdict() mengonversi ke dict, yang bekerja baik dengan JSON dan pprint.

namedtuple vs. dataclass

Jika kamu hanya butuh record ringan immutable, gunakan namedtuple. Jika kamu ingin method, nilai default, dan type hint terperinci, dataclass (dibahas dua artikel lagi) adalah alat yang tepat. Kekuatan namedtuple adalah kompatibilitas tuple — sempurna untuk mengganti tipe kembalian yang sudah ada seperti def f() -> tuple[int, int]: tanpa merusak pemanggil.

Definisikan namedtuple Point dan baca koordinat lewat nama.

① Impor namedtuple dari collections dan buat satu dengan class name "Point" dan field ["x", "y"]

② Bangun instance p dengan x=3, y=4

③ Cetak sebagai x: 3 y: 4 memakai akses bernama p.x dan p.y

Python Editor

Jalankan kode untuk melihat output

tambahan namedtuple — repr / index / _asdict

Di atas akses bernama gaya class, namedtuple memberi kamu akses indeks yang kompatibel dengan tuple, repr yang mudah dibaca, dan method _asdict untuk konversi dict. Kamu akan memakai ini untuk debugging, kompatibilitas dengan API yang sudah ada, dan serialisasi JSON, antara lain.

Pakai p dari Latihan 1 dan coba tiga pola akses tambahan.

print("repr:", p) untuk mencetak sebagai repr: Point(x=3, y=4)

② Pakai p[0] dan p[1] untuk akses indeks dan cetak sebagai Per indeks: 3 4

③ Pakai p._asdict() untuk mencetak sebagai Sebagai dict: {'x': 3, 'y': 4}

Python Editor

Jalankan kode untuk melihat output
QUIZ

Cek Pemahaman

Jawab setiap pertanyaan satu per satu.

Soal 1Apa cara paling ringkas untuk mendapatkan count kemunculan per elemen dari list nums dalam satu baris?

Soal 2Setelah membuat defaultdict(list), apa yang akses pertama ke key baru d["x"] berikan?

Soal 3Mana yang paling cocok ketika kamu ingin menyimpan hanya 5 item terbaru?