Daftar nilai ujian, nama produk, atau baris laporan hampir selalu lebih mudah dibaca setelah diurutkan. Data terurut juga menjadi syarat pencarian biner yang jauh lebih cepat daripada memeriksa setiap elemen. Go menyediakan dua package pengurutan: slices yang generik sejak Go 1.21, dan sort yang lebih tua. Chapter ini mengurutkan angka, string, sampai struct dengan beberapa kunci sekaligus memakai keduanya.
Mengurutkan Tipe Ordered #
slices.Sort mengurutkan slice bertipe ordered — seluruh bilangan dan string yang mendukung operator pembanding. Pengurutan berlangsung di tempat (in-place): isi slice lama berubah dan tidak ada slice baru yang dialokasikan:
angka := []int{50, 10, 40, 20, 30}
slices.Sort(angka)Fungsi slices.IsSorted memeriksa apakah sebuah slice sudah terurut dan mengembalikan bool — berguna untuk memverifikasi hasil sebelum dipakai pencarian biner.
Comparator dengan cmp.Compare #
Struct tidak dianggap ordered oleh slices.Sort, sehingga kita memberi tahu cara membandingkannya lewat slices.SortFunc. Fungsi ini menerima comparator: fungsi yang membandingkan dua elemen dan mengembalikan bilangan negatif, nol, atau positif. Package cmp menyediakan cmp.Compare yang menghasilkan ketiga nilai tersebut untuk tipe ordered, sehingga comparator untuk satu field cukup satu baris:
slices.SortFunc(siswa, func(a, b Siswa) int {
return cmp.Compare(a.Nilai, b.Nilai)
})
}Comparator di atas mengurutkan slice siswa menurut field Nilai secara menaik. Untuk urutan menurun, balik kedua argumennya menjadi cmp.Compare(b.Nilai, a.Nilai). Fungsi cmp.Less(a, b) menjawab pertanyaan apakah a lebih kecil dari b dan cocok dipakai pada API lawas yang meminta bool.
SortStableFunc dan Multi-Kunci #
slices.SortFunc tidak menjanjikan urutan relatif antara elemen yang dianggap seri. slices.SortStableFunc menjaga urutan relatif tersebut — penting ketika elemen seri masih berbeda pada field lain yang ingin dipertahankan. Pembandingan beberapa kunci sekaligus mengikuti pola berjenjang: bandingkan kunci pertama, lalu kunci kedua hanya jika kunci pertama seri:
slices.SortStableFunc(siswa, func(a, b Siswa) int {
if c := cmp.Compare(a.Umur, b.Umur); c != 0 {
return c
}
return cmp.Compare(b.Nilai, a.Nilai)
})
}Pada comparator di atas, umur dibandingkan menaik; ketika umur sama, nilai dibandingkan menurun karena argumen cmp.Compare sengaja dibalik.
Pencarian Binari dan Keanggotaan #
slices.BinarySearch mencari nilai pada slice terurut dan mengembalikan dua nilai: posisi yang cocok atau posisi penyisipan, serta bool keberadaan. slices.Contains menjawab ada-tidaknya sebuah nilai, dan slices.Index mengembalikan posisi kemunculan pertama atau -1. Ketiganya hanya membaca isi slice tanpa mengubahnya.
Clone, Reverse, dan Concat #
slices.Clone menyalin slice menjadi slice baru sehingga pengurutan salinan tidak menyentuh data asli. slices.Reverse membalik urutan elemen di tempat, dan slices.Concat menggabungkan beberapa slice menjadi satu slice baru. Ketiganya sering dirangkai: salin, urutkan, lalu balik bila urutan akhirnya perlu menurun.
Package sort Lama #
Sebelum Go 1.21, pengurutan memakai package sort: fungsi siap pakai seperti sort.Ints dan sort.Strings, atau sort.Slice dengan comparator func(i, j int) bool. Dasar keduanya adalah interface sort.Interface dengan kontrak tiga method: Len() int, Less(i, j int) bool, dan Swap(i, j int). Tanpa generics, package ini bekerja lewat tipe interface{} sehingga pemeriksaan tipe tidak bisa dilakukan saat kompilasi.
Program Utuh #
Berkas sort-demo.go merangkai seluruh materi chapter:
package main
import (
"cmp"
"fmt"
"slices"
"sort"
)
// Siswa menjadi contoh struct dengan dua field yang akan dibandingkan.
type Siswa struct {
Nama string
Umur int
Nilai float64
}
func main() {
// slices.Sort untuk tipe ordered: angka dan string.
angka := []int{50, 10, 40, 20, 30}
slices.Sort(angka)
fmt.Println("terurut :", angka)
fmt.Println("sorted :", slices.IsSorted(angka))
// BinarySearch mencari nilai pada slice yang sudah terurut.
posisi, ketemu := slices.BinarySearch(angka, 40)
fmt.Println("cari 40 :", posisi, ketemu)
_, ketemu = slices.BinarySearch(angka, 35)
fmt.Println("cari 35 :", ketemu)
// Contains dan Index memeriksa keanggotaan dan posisi.
fmt.Println("ada 30 :", slices.Contains(angka, 30))
fmt.Println("indeks 30:", slices.Index(angka, 30))
// Clone menyalin slice sehingga pengurutan tidak mengubah aslinya.
salinan := slices.Clone(angka)
slices.Reverse(salinan)
fmt.Println("asli :", angka)
fmt.Println("salinan :", salinan)
// SortFunc memakai comparator dari package cmp.
siswa := []Siswa{
{"Budi", 20, 3.4},
{"Siti", 22, 3.9},
{"Andi", 20, 3.1},
}
slices.SortFunc(siswa, func(a, b Siswa) int {
return cmp.Compare(a.Nilai, b.Nilai)
})
fmt.Println("nilai :", siswa)
// SortStableFunc dengan dua kunci: umur naik, lalu nilai turun.
slices.SortStableFunc(siswa, func(a, b Siswa) int {
if c := cmp.Compare(a.Umur, b.Umur); c != 0 {
return c
}
return cmp.Compare(b.Nilai, a.Nilai)
})
fmt.Println("2 kunci :", siswa)
// Package sort lama tetap tersedia untuk kode yang sudah ada.
legacy := []string{"jeruk", "apel", "mangga"}
sort.Strings(legacy)
fmt.Println("legacy :", legacy)
}Jalankan program dari folder chapter:
go run sort-demo.goOutput yang Dihasilkan:
terurut : [10 20 30 40 50]
sorted : true
cari 40 : 3 true
cari 35 : false
ada 30 : true
indeks 30: 2
asli : [10 20 30 40 50]
salinan : [50 40 30 20 10]
nilai : [{Andi 20 3.1} {Budi 20 3.4} {Siti 22 3.9}]
2 kunci : [{Budi 20 3.4} {Andi 20 3.1} {Siti 22 3.9}]
legacy : [apel jeruk mangga]Mari kita telaah baris demi baris program di atas:
- Baris 4-7: empat package diimpor —
cmp,fmt,slices, dansortlama. - Baris 11-15: struct
Siswamenyimpan tiga field yang menjadi bahan pembanding. - Baris 19-22: slice angka diurutkan in-place, lalu
IsSortedmemverifikasi hasilnya. - Baris 25-28:
BinarySearchmenemukan 40 di posisi 3 dan melaporkan 35 tidak ada. - Baris 31-32:
ContainsdanIndexmemeriksa keanggotaan angka 30. - Baris 35-38:
Clonemenyalin slice;Reversemembalik salinan sehinggaangkatetap terurut. - Baris 41-49:
SortFuncdengancmp.Comparemengurutkan siswa menurut nilai menaik. - Baris 52-58:
SortStableFuncmengurutkan menurut umur menaik lalu nilai menurun. - Baris 61-63:
sort.Stringsdari package lama mengurutkan nama buah.
Referensi #
- Dokumentasi package slices — fungsi pengurutan generik lengkap.
- slices.SortFunc — kontrak comparator negatif-nol-positif.
- Dokumentasi package cmp
—
ComparedanLessuntuk tipe ordered. - Dokumentasi package sort
— API lawas dan
sort.Interface.
Pengurutan sering berpasangan dengan map: program mengumpulkan data ke dalam map, lalu mengurutkan kuncinya agar output rapi. Chapter berikutnya membahas package maps beserta utilitas generiknya untuk mengkloning, menyalin, dan menyaring isi map.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
sort-demo.go
Unduh berkaspackage main
import (
"cmp"
"fmt"
"slices"
"sort"
)
// Siswa menjadi contoh struct dengan dua field yang akan dibandingkan.
type Siswa struct {
Nama string
Umur int
Nilai float64
}
func main() {
// slices.Sort untuk tipe ordered: angka dan string.
angka := []int{50, 10, 40, 20, 30}
slices.Sort(angka)
fmt.Println("terurut :", angka)
fmt.Println("sorted :", slices.IsSorted(angka))
// BinarySearch mencari nilai pada slice yang sudah terurut.
posisi, ketemu := slices.BinarySearch(angka, 40)
fmt.Println("cari 40 :", posisi, ketemu)
_, ketemu = slices.BinarySearch(angka, 35)
fmt.Println("cari 35 :", ketemu)
// Contains dan Index memeriksa keanggotaan dan posisi.
fmt.Println("ada 30 :", slices.Contains(angka, 30))
fmt.Println("indeks 30:", slices.Index(angka, 30))
// Clone menyalin slice sehingga pengurutan tidak mengubah aslinya.
salinan := slices.Clone(angka)
slices.Reverse(salinan)
fmt.Println("asli :", angka)
fmt.Println("salinan :", salinan)
// SortFunc memakai comparator dari package cmp.
siswa := []Siswa{
{"Budi", 20, 3.4},
{"Siti", 22, 3.9},
{"Andi", 20, 3.1},
}
slices.SortFunc(siswa, func(a, b Siswa) int {
return cmp.Compare(a.Nilai, b.Nilai)
})
fmt.Println("nilai :", siswa)
// SortStableFunc dengan dua kunci: umur naik, lalu nilai turun.
slices.SortStableFunc(siswa, func(a, b Siswa) int {
if c := cmp.Compare(a.Umur, b.Umur); c != 0 {
return c
}
return cmp.Compare(b.Nilai, a.Nilai)
})
fmt.Println("2 kunci :", siswa)
// Package sort lama tetap tersedia untuk kode yang sudah ada.
legacy := []string{"jeruk", "apel", "mangga"}
sort.Strings(legacy)
fmt.Println("legacy :", legacy)
}