Hash menyimpan kumpulan pasangan kunci dan nilai, dan Perl menandainya dengan karakter % di depan nama variabelnya. Berbeda dengan array yang diakses melalui nomor indeks, hash diakses melalui kunci berupa string, sehingga data tersusun menurut maknanya dan bukan posisinya. Topik ini membahas penulisan hash beserta fat comma, akses dan pengubahan entri, penelusuran kunci dan nilai dengan keys, values, dan each, serta alasan urutan hash tidak dapat diandalkan pada keluaran.
Mendeklarasikan hash dengan pasangan kunci dan nilai#
Hash dideklarasikan dengan my, lalu ditugaskan daftar pasangan. Setiap pasangan terdiri atas kunci dan nilai yang bergantian, dan Perl menyediakan penulisan fat comma berupa => untuk memisahkannya. Tanda => berperilaku seperti koma, tetapi mengizinkan kunci di sebelah kirinya ditulis tanpa tanda kutip, sehingga pasangan pensil => 24 terbaca seperti pemetaan yang sebenarnya. Bentuk ini hanya menghilangkan kutip pada kunci berupa kata tunggal, sedangkan kunci dengan spasi tetap memerlukan tanda kutip.
Akses satu nilai menggunakan tanda skalar dan kunci di dalam kurung kurawal, contohnya $stok{pensil}. Penugasan pada kunci baru menambah entri, sedangkan penugasan pada kunci lama mengganti nilainya. Banyaknya pasangan diperoleh melalui konteks scalar, misalnya scalar(keys %stok), dan pola ini melibatkan fungsi keys yang dibahas pada bagian berikutnya.
Kunci pada hash bersifat tunggal, sehingga dua pasangan dengan kunci yang sama tidak dapat berdampingan. Apabila daftar inisialisasi memuat kunci yang berulang, pasangan yang ditulis paling akhir yang dipertahankan, dan nilai sebelumnya tertimpa tanpa peringatan. Kunci disimpan sebagai string, sehingga $stok{10} dan $stok{"10"} menunjuk entri yang sama meskipun ditulis dengan cara berbeda. Hash utuh pada konteks list juga berperilaku sebagai daftar biasa, yaitu %stok terurai menjadi urutan kunci dan nilai yang bergantian. Deklarasi dengan kurung pada dasarnya adalah penugasan daftar pasangan tersebut ke variabel hash.
use strict;
use warnings;
# hash persediaan alat tulis, ditulis dengan fat comma agar mudah dibaca
my %stok = (
pensil => 24,
buku => 10,
penghapus => 7,
);
# akses satu nilai lewat kuncinya
print "Stok pensil : $stok{pensil}\n";
print "Stok penghapus: $stok{penghapus}\n";
# penugasan pada kunci baru menambah entri, pada kunci lama mengubahnya
$stok{penggaris} = 5;
$stok{buku} = 12;
print "Stok buku : $stok{buku}\n";
print "Stok penggaris: $stok{penggaris}\n";
# banyaknya pasangan kunci dan nilai didapat lewat konteks scalar
print "Banyak entri : ", scalar(keys %stok), "\n";Stok pensil : 24
Stok penghapus: 7
Stok buku : 12
Stok penggaris: 5
Banyak entri : 4Menelusuri kunci dan nilai dengan keys dan values#
Fungsi keys mengembalikan daftar seluruh kunci pada hash, sedangkan values mengembalikan daftar seluruh nilainya. Kedua daftar itu dapat ditelusuri dengan perulangan foreach, yang bentuknya foreach my $elemen (daftar) dan menelusuri setiap anggota daftarnya secara berurutan.
Urutan kunci yang dikembalikan keys tidak teratur dan berbeda-beda antar eksekusi, karena Perl menyimpan hash dalam susunan internal yang bukan urutan penulisannya. Pasangan yang dideklarasikan lebih dahulu belum tentu keluar lebih dahulu, dan urutannya bahkan dapat berubah antar proses yang menjalankan skrip yang sama. Karena itu, contoh yang menampilkan keluaran selalu menggunakan sort keys %hash, yaitu daftar kunci yang diurutkan sebelum ditelusuri. Dengan pengurutan ini, keluaran skrip menjadi sama di setiap eksekusi dan dapat diperiksa dengan mudah. Daftar nilai dari values juga tidak teratur, sehingga pada skrip berikut nilainya diurutkan dengan sort numerik sebelum dicetak.
use strict;
use warnings;
# catatan jumlah pengunjung perpustakaan per bulan
my %pengunjung = (
Januari => 120,
Februari => 95,
Maret => 140,
April => 110,
);
# keys mengembalikan daftar kunci pada hash
# sort mengurutkannya agar keluaran sama di setiap eksekusi
foreach my $bulan (sort keys %pengunjung) {
print "$bulan: $pengunjung{$bulan}\n";
}
# values mengembalikan daftar nilai pada hash
my @jumlah = values %pengunjung;
print "Banyak entri : ", scalar(@jumlah), "\n";
# urutan nilai juga perlu dirapikan sendiri bila keluaran harus tetap
my @terurut = sort { $a <=> $b } @jumlah;
print "Nilai terurut : @terurut\n";April: 110
Februari: 95
Januari: 120
Maret: 140
Banyak entri : 4
Nilai terurut : 95 110 120 140each dan alternatif modernnya#
Fungsi each mengembalikan satu pasangan kunci dan nilai pada setiap pemanggilan, lalu berpindah ke pasangan berikutnya pada pemanggilan selanjutnya. Posisi terakhirnya disimpan pada hash itu sendiri, sehingga pemanggilan berikutnya melanjutkan penelusuran dari titik terakhir. Pola penggunaannya berupa perulangan while yang membaca pasangan sampai habis, sebagaimana bentuk berikut.
# tidak-dijalankan
# each mengembalikan pasangan kunci dan nilai satu per satu
while (my ($bulan, $jumlah) = each %pengunjung) {
print "$bulan: $jumlah\n";
}Potongan di atas tidak dijalankan di sandbox karena keluarannya tidak dapat dijadikan acuan. Setiap eksekusi menghasilkan urutan yang berbeda, sebab each mengikuti susunan internal hash yang diacak. Selain urutannya, iterator internal each juga menjadi sumber kesalahan yang halus. Apabila perulangan berhenti sebelum pasangan habis, misalnya karena last, posisi internalnya tertinggal, dan penelusuran hash yang sama pada bagian lain skrip akan mulai dari tengah.
Oleh karena itu, foreach keys disarankan sebagai penggantinya dalam iterasi modern. Fungsi keys mengembalikan daftar kunci yang utuh sekaligus, sehingga tidak ada posisi yang tersimpan di antara pemanggilan. Penelusuran foreach my $kunci (sort keys %hash) sekaligus menyelesaikan tiga hal, yaitu keutuhan daftar, urutan yang teratur, dan ketiadaan posisi tersimpan.
Posisi iterator each dapat dipulihkan dengan keys atau values, karena evaluasi kedua fungsi itu mengembalikan iterator hash ke titik awalnya. Setelah seluruh pasangan habis dibaca, each mengembalikan list kosong, dan panggilan berikutnya memulai penelusuran kembali dari awal. Perubahan isi hash selama penelusuran each berlangsung membuat perilakunya tidak terdefinisi, sehingga entri dapat terlewat atau terbaca dua kali. Alternatif foreach keys bebas dari masalah ini karena keys menyalin seluruh kunci menjadi daftar baru sebelum perulangan dimulai. Penambahan entri selama perulangan pun tidak mengacaukan daftar yang sedang ditelusuri, sebab daftarnya sudah tetap sejak awal.
Kesalahan umum#
Kesalahan pertama adalah mengandalkan urutan penulisan saat mendeklarasikan hash. Hash bukan array, dan pasangan yang ditulis lebih dahulu tidak menempati posisi pertama, sehingga pembacaan berbasis urutan pasti berujung pada hasil yang acak. Penyortiran pada keys atau values merupakan satu-satunya cara menghasilkan urutan yang teratur.
Kesalahan kedua terjadi pada kunci yang bukan kata tunggal. Fat comma hanya menghilangkan tanda kutip untuk kunci berupa kata tunggal, sehingga kunci seperti buku tulis wajib ditulis "buku tulis", baik pada deklarasi maupun pada akses $stok{"buku tulis"}. Hash juga peka huruf besar kecil, sehingga Buku dan buku merupakan dua kunci yang berbeda. Kesalahan ketiga adalah menganggap kunci yang belum ditugaskan sebagai nol atau string kosong, padahal nilainya undef, dan perlakuan yang tepat terhadap kondisi itu dibahas pada topik tersendiri.
Ringkasan#
- Hash bertanda
%menyimpan pasangan kunci dan nilai, ditulis dengan fat comma=>, dan diakses melalui$hash{kunci}. keysmengembalikan daftar kunci,valuesmengembalikan daftar nilai, dan keduanya berurutan acak, sehingga keluaran yang deterministik memerlukansort.eachmengembalikan pasangan satu per satu dengan posisi tersimpan, sehingga iterasi modern lebih disarankan melaluiforeach keys.- Penugasan pada kunci menambah atau mengubah entri, sedangkan
scalar(keys %hash)memberikan banyaknya pasangan.
Referensi#
- perldata — Perl documentation — Menguraikan hash, pasangan kunci dan nilai, serta urutan internalnya.
- perlfunc — Perl documentation
— Daftar fungsi bawaan Perl, termasuk
keys,values, daneach.