Menghitung frekuensi, mengelompokkan transaksi per pelanggan, menjaga riwayat terakhir — semuanya bisa ditulis dengan dict dan if, tetapi kodenya penuh pola berulang. Module collections menyediakan container khusus yang menghapus pola-pola tersebut. Pada Chapter ini kita bahas lima container beserta kapan masing-masing layak dipilih, melengkapi pemahaman dict dasar dari Chapter Dictionary.

Counter: Menghitung Frekuensi #

Class Counter adalah dictionary yang nilainya otomatis menjadi jumlah kemunculan:

python
from collections import Counter

suara = ["siti", "budi", "siti", "andi", "siti", "budi"]
hasil_suara = Counter(suara)

print(hasil_suara)
print(hasil_suara.most_common(2))

Output yang Dihasilkan:

text
Counter({'siti': 3, 'budi': 2, 'andi': 1})
[('siti', 3), ('budi', 2)]

Membuat Counter dari list langsung menghitung frekuensi setiap elemen. Method most_common(k) lalu menjawab pertanyaan “siapa dua teratas” dalam satu panggilan — pola yang dikenal sebagai top-k — tanpa kita menulis loop penghitung manual.

defaultdict: Pengelompokan Tanpa Setdefault #

Class defaultdict menghilangkan pengecekan if nama not in dict saat membangun kelompok. Kita cukup menentukan factory nilai bawaan saat konstruksi:

python
from collections import defaultdict

penjualan = [("Budi", 120), ("Siti", 200), ("Budi", 80), ("Andi", 150)]

per_sales = defaultdict(list)
for nama, nilai in penjualan:
    per_sales[nama].append(nilai)

print(dict(per_sales))

total_per_sales = defaultdict(int)
for nama, nilai in penjualan:
    total_per_sales[nama] += nilai

print(dict(total_per_sales))

Output yang Dihasilkan:

text
{'Budi': [120, 80], 'Siti': [200], 'Andi': [150]}
{'Budi': 200, 'Siti': 200, 'Andi': 150}

Mari kita bedah dua pola di atas:

  1. Baris 5 (defaultdict(list)): saat key baru diakses, defaultdict otomatis membuat list kosong, sehingga per_sales[nama].append(nilai) langsung berjalan tanpa pengecekan apakah key sudah ada.
  2. Baris 11 (defaultdict(int)): nilai bawaan int() adalah 0, sehingga operasi += nilai pada key baru dimulai dari nol. Pola ini ideal untuk akumulasi total per kelompok.

deque: Antrian Dua Arah #

Class deque (double-ended queue) menambah dan menghapus elemen di kedua ujung dengan kompleksitas O(1), berbeda dengan list yang operasi pop(0)-nya O(n) karena harus menggeser seluruh elemen. Parameter maxlen membuatnya cocok untuk riwayat terbatas:

python
from collections import deque

riwayat = deque(maxlen=3)
for halaman in ["beranda", "produk", "keranjang", "pembayaran"]:
    riwayat.append(halaman)

print(list(riwayat))

riwayat.appendleft("promo")
print(list(riwayat))

Output yang Dihasilkan:

text
['produk', 'keranjang', 'pembayaran']
['promo', 'produk', 'keranjang']

Karena maxlen=3, penambahan "pembayaran" otomatis membuang "beranda" yang paling lama. Method appendleft("promo") kemudian menyisipkan di depan sambil membuang elemen paling kanan ("pembayaran") — antrian tetap berisi tepat tiga halaman.

OrderedDict dan ChainMap #

Sejak Python 3.7, dict bawaan menjamin urutan penyisipan, sehingga OrderedDict jarang dibutuhkan. Dua fitur yang masih membuatnya relevan: method move_to_end() untuk memindahkan key, dan perbandingan == yang memperhatikan urutan (dua OrderedDict dengan isi sama tetapi urutan beda dianggap tidak sama).

Class ChainMap merangkai beberapa dictionary menjadi satu tampilan; pencarian key dilakukan dari peta pertama:

python
from collections import ChainMap

config_default = {"debug": False, "port": 8000, "host": "127.0.0.1"}
config_lokal = {"debug": True}

config_aktif = ChainMap(config_lokal, config_default)

print(config_aktif["debug"])
print(config_aktif["port"])

Output yang Dihasilkan:

text
True
8000

Key "debug" diambil dari config_lokal yang berada di depan, sedangkan key "port" yang tidak ada di sana diteruskan ke config_default. Pola ini tepat untuk berlapis konfigurasi: default aplikasi → environment → argumen command line, tanpa menggabungkan dictionary secara fisik.

Memilih Container yang Tepat #

ContainerPertanyaan kunciContoh nyata
CounterPerlu menghitung atau memberi peringkat?Top produk terlaris
defaultdictPerlu mengelompokkan atau mengakumulasi?Penjualan per sales
dequePerlu antrian/riwayat dengan ujung cepat?Riwayat navigasi
OrderedDictPerlu memindah urutan atau membandingkan urutan?Cache LRU manual
ChainMapPerlu berlapis konfigurasi dengan prioritas?Default + override lokal

Kelima container ini bekerja mulus dengan iterator, dan pada Chapter itertools kita akan melihat bagaimana combinatoric seperti groupby() menghasilkan data yang siap ditampung langsung oleh defaultdict.