Mengurutkan Array

Keluarga sort/usort/ksort dan callback perbandingan.

Daftar isi

Pengurutan array pada PHP dilakukan oleh satu keluarga fungsi yang bekerja langsung pada variabelnya. Topik ini membahas pembagian tugas keluarga tersebut, pengurutan berdasarkan nilai dan berdasarkan kunci, callback perbandingan dengan usort() beserta operator <=>, dan flag jenis perbandingan yang mengatur cara dua nilai dibandingkan. Setelah membacanya, fungsi pengurutan dapat dipilih sesuai bentuk array dan kebutuhan urutannya.

Keluarga fungsi sort dan sifatnya di tempat#

Seluruh fungsi pengurutan PHP mengubah array pada variabel asalnya secara langsung, atau in place, dan hanya mengembalikan true sebagai tanda keberhasilan. Tidak ada salinan array hasil urutan yang dikembalikan, sehingga array yang diurutkan adalah array yang dikirim sebagai argumen. Nama fungsinya menunjukkan dasar pengurutan dan cara kuncinya diperlakukan, sebagaimana dirangkum pada tabel berikut.

FungsiDasar pengurutanKunci hasil
sort() dan rsort()nilai naik dan nilai turundiganti indeks baru
asort() dan arsort()nilai naik dan nilai turundipertahankan
ksort() dan krsort()kunci naik dan kunci turundipertahankan
usort(), uasort(), uksort()callback perbandinganusort() mengganti kunci, dua lainnya mempertahankan

Tabel tersebut menunjukkan dua pertanyaan yang menentukan pilihan fungsi. Pertama, nilai atau kunci mana yang menjadi dasar urutan. Kedua, apakah hubungan antara kunci dan nilai perlu dipertahankan. Array asosiatif hampir selalu memerlukan asort() atau ksort(), sedangkan list padat dapat memakai sort() tanpa kehilangan apa pun.

Mengurutkan berdasarkan nilai atau kunci#

Fungsi asort() mengurutkan elemen menurut nilainya tanpa memutus hubungan kunci dan nilai, sedangkan ksort() mengurutkan menurut kuncinya. Fungsi sort() mengurutkan nilai dan menyusun ulang kunci menjadi indeks berurutan mulai dari 0, sehingga kunci string pada array asosiatif hilang. Perbedaan ketiganya paling jelas dilihat pada satu data yang sama.

Contoh berikut mengurutkan array stok gudang tiga kali dengan tiga fungsi berbeda, dan setiap hasil dicetak dengan print_r().

php urut-nilai-kunci.php
<?php

$stok = ['kertas' => 120, 'spidol' => 45, 'penghapus' => 60];

$perNilai = $stok;
asort($perNilai);
print_r($perNilai);

$perKunci = $stok;
ksort($perKunci);
print_r($perKunci);

$indeks = $stok;
sort($indeks);
print_r($indeks);
text Keluaran
Array
(
    [spidol] => 45
    [penghapus] => 60
    [kertas] => 120
)
Array
(
    [kertas] => 120
    [penghapus] => 60
    [spidol] => 45
)
Array
(
    [0] => 45
    [1] => 60
    [2] => 120
)

Hasil pertama tersusun menurut nilai dari 45 hingga 120 dengan kunci yang tetap menempel pada barangnya. Hasil kedua tersusun menurut kunci secara alfabetis. Hasil ketiga kehilangan kunci string dan berubah menjadi indeks 0 sampai 2, sehingga bentuk sort() hanya tepat untuk array terindeks.

usort dan callback perbandingan#

Fungsi usort() mengurutkan nilai dengan callback perbandingan yang ditentukan sendiri, sedangkan uasort() dan uksort() memakai bentuk yang sama untuk nilai dan kunci tanpa membuang kunci. Callback menerima dua elemen dan mengembalikan bilangan bulat, yaitu negatif apabila elemen pertama harus berada sebelum elemen kedua, nol apabila keduanya setara, dan positif apabila elemen pertama harus berada sesudahnya.

Operator <=> menuliskan kontrak tersebut dalam satu ekspresi karena menghasilkan -1, 0, atau 1 sesuai perbandingan dua nilai. Untuk urutan turun, cukup menukar posisi operan. Pengurutan dengan dua kriteria dituliskan dengan membandingkan array berisi kedua kriteria, dan urutan operannya mengatur arah setiap kriteria.

Contoh berikut mengurutkan peserta dari nilai tertinggi, lalu menyelesaikan nilai yang sama menurut nama secara alfabetis.

php urut-usort.php
<?php

$peserta = [
    ['nama' => 'Ali', 'nilai' => 85],
    ['nama' => 'Citra', 'nilai' => 78],
    ['nama' => 'Budi', 'nilai' => 85],
];

usort($peserta, fn(array $a, array $b) => [$b['nilai'], $a['nama']] <=> [$a['nilai'], $b['nama']]);

foreach ($peserta as $p) {
    echo $p['nama'], ': ', $p['nilai'], "\n";
}
text Keluaran
Ali: 85
Budi: 85
Citra: 78

Elemen dengan nilai 85 mendahului nilai 78 karena operan nilai ditulis terbalik untuk urutan turun. Ali dan Budi yang sama-sama memperoleh 85 kemudian dipisahkan oleh kriteria nama yang berarah naik, sehingga hasilnya menurun pada nilai dan menaik pada nama.

Flag jenis perbandingan#

Fungsi pengurutan menerima flag yang mengatur cara dua nilai dibandingkan. Flag SORT_REGULAR menjadi pilihan bawaan yang membandingkan nilai tanpa mengubah tipenya, sedangkan SORT_NUMERIC memperlakukan setiap nilai sebagai angka dan SORT_STRING memperlakukannya sebagai string. Pilihan flag menentukan hasil pada array yang isinya string angka, karena urutan string membandingkan karakter demi karakter.

Contoh berikut mengurutkan kode yang seluruhnya berupa string angka dengan dua flag berbeda.

php urut-flag.php
<?php

$kode = ['10', '9', '2'];

$perString = $kode;
sort($perString, SORT_STRING);
print_r($perString);

$perAngka = $kode;
sort($perAngka, SORT_NUMERIC);
print_r($perAngka);
text Keluaran
Array
(
    [0] => 10
    [1] => 2
    [2] => 9
)
Array
(
    [0] => 2
    [1] => 9
    [2] => 10
)

Pembanding string menempatkan '10' di depan karena karakter '1' lebih kecil daripada '2' dan '9', sedangkan pembanding angka menempatkannya di belakang karena nilai 10 lebih besar. Menentukan flag secara eksplisit membuat maksud pengurutan tidak bergantung pada tipe bawaan datanya.

Kesalahan umum#

  • Memakai sort() pada array asosiatif. Kunci string diganti indeks baru sehingga hubungan kunci dan nilai hilang. Gunakan asort() apabila kuncinya perlu dipertahankan.
  • Menugaskan hasil fungsi pengurutan ke variabel. Nilai kembaliannya adalah true, bukan array hasil urut, sehingga variabel penampungnya berisi boolean. Panggil fungsi pengurutan sebagai pernyataan tersendiri pada variabel yang akan diurutkan.
  • Menuliskan callback usort() yang tidak konsisten. Callback yang menghasilkan urutan berlawanan untuk pasangan yang sama membuat hasil tidak dapat dipastikan. Pastikan callback memberikan hasil yang konsisten untuk setiap pasangan nilai, dan operator <=> membantu menjaganya.
  • Mengira usort() mempertahankan kunci. Fungsi ini menyusun ulang kunci menjadi indeks baru, sehingga array asosiatif memerlukan uasort().

Ringkasan#

  • Seluruh fungsi pengurutan bekerja langsung pada variabel asalnya dan mengembalikan true, bukan array hasil urut.
  • sort() dan usort() mengganti kunci dengan indeks baru, sedangkan asort(), ksort(), uasort(), dan uksort() mempertahankannya.
  • Callback perbandingan mengembalikan bilangan negatif, nol, atau positif, dan operator <=> menuliskan kontrak itu dalam satu ekspresi.
  • Flag SORT_STRING dan SORT_NUMERIC mengatur cara dua nilai dibandingkan, dan pilihannya menentukan hasil pada data string angka.

Referensi#