Skip to content

Bagian 1 | Algorithm and Data Structure in Go

Published: at 12:47 AM

Table of Contents

Open Table of Contents

Pengenalan

Algoritma adalah langkah atau tahapan untuk menyelesaikan persoalan, jadi bisa di katakan algoritma seseorang dalam menyelesaikan masalah itu dapat berbeda-beda, pada postingan ini akan membahas data struktur terlebih dulu yang harapannya bisa dikembangkan lebih lanjut oleh diri kita, ibaratnya seperti mempelajari operasi penjumlahan, pengurangan, perkalian dan pembagian, operasi tersebut merupakan dasar dari cara seseorang menyelesaikan permasalahan matematika.

Agar lebih mudah mengerti algoritma yang sudah ada, saya coba untuk belajar dan mengulas kembali pada bagian struktur data, jadi ada cukup banyak struktur data yang saya pelajari, seperti pada postingan ini terdapat array, slice, map, struct untuk penjelasan dan contohnya saya uraikan di bawah ini

Data Structure

Array

Sering disebut sebagai kumpulan dari item atau elemen yang memiliki tipe sama (homogen),

  1. Bagaimana array digunakan?
  • Menyimpan data yang di proses
  • Melakukan implementasi Stack dan Queue
  • Representasi data ke dalam tabel dan matriks
  • Membuat data struktur yang dinamis seperti linked list dan tree
  1. Operasi pada Array Karena go sangat strict dengan tipe data dan struktur data, kita tidak dapat leluasa manipulasi array seperti menambahkan elemen, menghapus elemen pada go, tetapi menurut saya ini menjadi nilai tambah karena menjadi lebih konsisten, berikut cara untuk inisialisasi array pada go, mengubah nilai dari indeks tertentu, dan melakukan iterasi pada array

Inisialisasi Array dan mengubah nilai elemen pada array

Pada Go dalam melakukan inisialisasi array dapat dilakukan dengan dua cara yaitu:

  • inisialisasi langsung simpan elemen
  • inisialisasi definisi elemen by index Lalu untuk pengoperasian seperti memanggil array, atau mengambil elemen pada array serupa dengan bahasa pemrograman pada python, cukup panggil array beserta indexnya
// inisialisasi array dan mengganti item
package main

import "fmt"

func main() {

	// inisialisasi array cara 1
	kardus := [4]string{"Pisang", "Susu", "Sendok", "Botol"}

	// inisialisasi array cara 2
	var kumpulan_data [4]int
	kumpulan_data[0] = 3
	kumpulan_data[1] = 4
	kumpulan_data[2] = 5
	kumpulan_data[3] = 6

	// mengganti nilai array
	kardus[2] = "Garpu"
	kumpulan_data[0] = 1

	// cetak array
	fmt.Println(kardus)
	fmt.Println(kumpulan_data)
	fmt.Println("elemen pada kardus indeks ke-2:", kardus[0:3])
	fmt.Println("elemen pada kumpulan_data indeks ke-0:", kumpulan_data[0])

}
output:
[Pisang Susu Garpu Botol]
[1 4 5 6]
elemen pada kardus indeks ke-2: [Pisang Susu Garpu]
elemen pada kumpulan_data indeks ke-0: 1

Iterasi pada array

Untuk menyebutkan elemen pada array secara berulang dapat dilakukan dengan cara looping, dapat dengan dua cara yaitu:

  • for loop
  • for … range
// iterasi array sequential

package main

import "fmt"

func main() {
	kardus := [4]string{"Pisang", "Susu", "Sendok", "Botol"}

	for i := 0; i < len(kardus); i++ {
		fmt.Println(kardus[i])
	}
}
output:
Pisang
Susu
Sendok
Botol

Jika iterasi menggunakan for… range maka memiliki dua argumen yang akan di bawa saat iterasi yaitu indeks dan value, jika hanya memberikan satu argumen maka return nya adalah nilai indeksnya

// / iterasi array sequential menggunakan range
package main

import "fmt"

func main() {
	kardus := [4]string{"Pisang", "Susu", "Sendok", "Botol"}

	//dua argumen (index, value)
	for index, value := range kardus {
		fmt.Println(index, value)
	}

	fmt.Println("============")

	//satu argumen
	for index := range kardus {
		fmt.Println(kardus[index])
	}
}
output:
0 Pisang
1 Susu
2 Sendok
3 Botol
============
Pisang
Susu
Sendok
Botol

Untuk melakukan reverse pada elemen array dapat menggunakan cara berikut, singkatnya i = 0, j = len(s)-1 untuk melakukan penukaran elemen, pada go dapat dilakukan dengan cara s[i], s[j] = s[j], s[i] artinya s[i] = s[j], s[j] = s[i]

package main

import "fmt"

func main() {

	s := [4]string{"Pisang", "Susu", "Sendok", "Botol"}

	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
		s[i], s[j] = s[j], s[i]
	}

	fmt.Println(s)
}
output:
[Botol Sendok Susu Pisang]

Lalu untuk memanggil elemen pada array secara reverse dapat dilakukan for loop dengan iterasi menurun (decrement)

// iterasi array reverse

package main

import "fmt"

func main() {
	kardus := [4]string{"Pisang", "Susu", "Sendok", "Botol"}

	for i := len(kardus) - 1; i >= 0; i-- {
		fmt.Println(kardus[i])
	}
}
output:
Botol
Sendok
Susu
Pisang

Slice

Pada go slice merupakan struktur data yang lebih fleksibel dibandingkan dengan array, karena tidak perlu mendefinisikan panjang elemennya, hanya dengan hal itu kita dapat melakukan banyak operasi pada slice seperti menambahkan elemen, menghapus elemen, dan memanipulasi elemen lebih mudah, tetapi karena kemudahannya terkadang slice dapat menjadi tidak konsisten dibandingkan array

Slice dapat melakukan operasi pengambilan data dari array yang disimpan ke dalam suatu koleksi yang dinamis, jadi mudahnya, slice itu mengambil data dari array dan disimpan sebagai koleksi yang dinamis (ukurannya dapat bertambah atau berkurang), kita akan coba membuat slice, dan melakukan manipulasi slice, untuk iterasi slice sama seperti pada array.

Membuat Slice

package main

import "fmt"

func main() {
	//inisialisasi array
	prima := [8]int{2, 3, 5, 7, 11, 13, 17, 19}

	// melakukan slicing elemen array dan disimpan dalam slice
	primaSlice := prima[:5]

	fmt.Println(prima) //output array
	fmt.Println(primaSlice) //output slice
}
Output:
[2 3 5 7 11 13 17 19]
[2 3 5 7 11]

Dalam Go kita dapat membuat slice dengan fungsi make fungsi tersebut membutuhkan dua parameter wajib (tipe data dan panjang slice) dan satu parameter opsional (kapasitas), kapasitas digunakan untuk slice memesan alokasi memori pada sistem kita, jika kita melakukan input lebih dari kapasitas maka slice akan melakukan alokasi memori ulang sebesar jumlah kapasitas slice saat itu.

package main

import "fmt"

func main() {
	slice1 := make([]bool, 3)   // capacity = 0
	slice2 := make([]int, 3, 5) // menambahkan capacity=5
	fmt.Println(slice1)
	fmt.Println(slice2)
}
Output:
[false false false]
[0 0 0]

Jika kita memasukkan argumen length lebih besar dibandingkan argumen capacity maka akan menampilkan error pada output yang menyatakan argumen length dan capacity kebalik, seperti pada kode di bawah ini

package main

import "fmt"

func main() {
	slice2 := make([]int, 6, 5) // menambahkan length=6 capacity=5
	fmt.Println(slice2)
}
Output:
invalid argument: length and capacity swapped

Baris kode berikut ini juga termasuk cara untuk membuat slice

package main

import "fmt"

func main() {
	var prima []int
	prima = []int{2, 3, 5, 7, 9, 11, 13, 19}
	fmt.Println(prima)
}

Manipulasi Slice

Untuk melakukan manipulasi serupa dengan array, tetapi karena slice memiliki panjang yang dinamis disini kita dapat menggunakan fungsi append untuk menambahkan elemen pada slice

package main

import "fmt"

func main() {
	var slice1 []int
	slice1 = []int{2, 3, 5, 7, 9, 11, 13, 19}
	slice2 := make([]bool, 3, 5) // output: [false, false, false]

	// menambahkan elemen pada slice
	slice1 = append(slice1, 23, 29)
	slice2 = append(slice2, false, true)

	// mengganti elemen pada slice
	slice2[0] = true

	fmt.Println(slice1)
	fmt.Println(slice2)
}
Output:
[2 3 5 7 9 11 13 19 23 29]
[true false false false true]

Map

Map merupakan tipe struktur data yang berbentuk key dan value seperti object pada JavaScript dan dictionary pada python, key dapat dikatakan sebagai identifier sehingga harus bersifat unik dengan tipe data yang bebas, untuk nilai default dari variabel map adalah nil maka harus di inisialisasi

Membuat Map

Untuk membuat map terdapat tiga cara tetapi bisa saja dengan variasi yang berbeda, caranya antara lain:

  1. deklarasi lalu inisialisasi terpisah, untuk cara pertama deklarasi variable map lalu dipisahkan inisialisasinya
package main

import "fmt"

func main() {
	var stokBuah map[string]int //deklarasi tipe data untuk key dan value
	stokBuah = map[string]int{}
	fmt.Println(stokBuah)
}
  1. inisialisasi secara eksplisit, untuk cara ini deklarasi variable map dan inisialisasi di gabung dalam satu baris.
package main

import "fmt"

func main() {
	stokSayur := map[string]int{}
	fmt.Println(stokSayur)
}
  1. Menggunakan make, kelebihan menggunakan make adalah alokasi memorinya, dengan menggunakan make maka memori akan di reservasi untuk membuat map kosong yang akan ditugaskan nanti.
package main

import "fmt"

func main() {
	stokDaging := make(map[string]int) //deklarasi tipe data untuk key dan value
	stokDaging["ayam"] = 400
	stokDaging["sapi"] = 300
	fmt.Println(stokDaging)
}

Menambahkan dan Mengakses Nilai

Untuk menambahkan atau mengisi nilai map terdapat 2 cara yang dapat dilakukan, yaitu dengan cara key-value pairs dan objek literal

package main

import "fmt"

func main() {

	// 1. key-value pairs
	var stokBuah map[string]int //deklarasi tipe data untuk key dan value
	stokBuah = map[string]int{} //inisialisasi map
	stokBuah["mangga"] = 40
	stokBuah["pisang"] = 30
	stokBuah["melon"] = 14
	fmt.Println(stokBuah)
	fmt.Println("akses nilai mangga: ", stokBuah["mangga"])

	//2. objek literal
	stokSayur := map[string]int{
		"buncis": 30,
		"tauge":  42,
		"kol":    33,
		"selada": 45,
	}
	fmt.Println(stokSayur)
	fmt.Println("akses nilai kol: ", stokSayur["kol"])

	//khusus. untuk make menggunakan key-value pairs
	stokDaging := make(map[string]int) //deklarasi tipe data untuk key dan value
	stokDaging["ayam"] = 400
	stokDaging["sapi"] = 300
	fmt.Println(stokDaging)
	fmt.Println("akses nilai sapi: ", stokDaging["sapi"])
}
output:
map[mangga:40 melon:14 pisang:30]
akses nilai mangga:  40
map[buncis:30 kol:33 selada:45 tauge:42]
akses nilai kol:  33
map[ayam:400 sapi:300]
akses nilai sapi:  300

Membuat Nested Map

Untuk membuat nested map maka diperlukan inisialisasi map sebanyak n, jika ingin nested menjadi dua map maka inisialisasi sebanyak 2.

package main

import "fmt"

func main() {
	stokDagang := map[string]map[string]int{
		"sayuran": {"buncis": 30,
			"tauge":  42,
			"kol":    33,
			"selada": 45},
		"daging": {"ayam": 500,
			"sapi": 300},
	}
	fmt.Println(stokDagang)
	fmt.Println("akses nilai sayuran: ", stokDagang["sayuran"])
	fmt.Println("akses nilai daging: ", stokDagang["daging"])
	fmt.Println("akses nilai kol: ", stokDagang["sayuran"]["kol"])
	fmt.Println("akses nilai sapi: ", stokDagang["daging"]["sapi"])
}
output:
map[daging:map[ayam:500 sapi:300] sayuran:map[buncis:30 kol:33 selada:45 tauge:42]]
akses nilai sayuran:  map[buncis:30 kol:33 selada:45 tauge:42]
akses nilai daging:  map[ayam:500 sapi:300]
akses nilai kol:  33
akses nilai sapi:  300

Iterasi Item Map

untuk melakukan iterasi item sebenarnya sama seperti sebelumnya, selagi paham cara akses map maka iterasi dapat dilakukan, untuk saat ini kita coba iterasikan menggunakan for-range kita akan coba lakukan iterasi untuk map biasa dan nested map.

  1. Iterasi Map
package main

import "fmt"

func main() {
	stokSayur := map[string]int{
		"buncis": 30,
		"tauge":  42,
		"kol":    33,
		"selada": 45,
	}

	for key, value := range stokSayur {
		fmt.Println(key, value)
	}
}
output:
buncis 30
tauge 42
kol 33
selada 45
  1. Iterasi Nested Map, pada nested map iterasi yang dilakukan sebanyak nesting yang dilakukan
package main

import "fmt"

func main() {
	stokDagang := map[string]map[string]int{
		"sayuran": {"buncis": 30,
			"tauge":  42,
			"kol":    33,
			"selada": 45},
		"daging": {"ayam": 500,
			"sapi": 300},
	}

	for category, items := range stokDagang {
		fmt.Println("----------------")
		fmt.Println(category, ":")
		for item, quantity := range items {
			fmt.Println(item, quantity)
		}
	}
}
output:
----------------
sayuran :
buncis 30
tauge 42
kol 33
selada 45
----------------
daging :
sapi 300
ayam 500

Cek key yang sudah ada

Karena go dapat melakukan multiple return values maka kita bisa manfaatkan hal tersebut untuk melakukan pengecekan, cara kerja metode tersebut cukup mudah, kita hanya perlu assign dua variable maka masing-masing variable akan mengembalikan nilainya, karena saat memanggil map akan membawa dua nilai yaitu nilai key dan statusnya (true atau false) maka variable akan mengembalikan kedua nilai tersebut.

package main

import "fmt"

func main() {
	stokSayur := map[string]int{
		"buncis": 30,
		"tauge":  42,
		"kol":    33,
		"selada": 45,
	}
	fmt.Println(stokSayur)
	fmt.Println("akses nilai kol: ", stokSayur["kol"])

	// cek elemen map

	//jika ada elemen
	element, status := stokSayur["selada"]
	fmt.Println(element, status)

	//jika tidak ada elemen
	element, status = stokSayur["bayam"]
	fmt.Println(element, status)

	//jika tidak perlu element masukkan blank identifier _
	_, status = stokSayur["kol"]
	fmt.Println(status)
}
output:
map[buncis:30 kol:33 selada:45 tauge:42]
akses nilai kol:  33
45 true
0 false

Pada kode diatas dilakukan assign variable element dan status ke map tertentu, map akan mengembalikan dua nilai yaitu value dari key dan statusnya, jika elemen pada map stokSayur["selada"] ada maka akan mengembalikan value dari key “selada” dan statusnya true. jika tidak ingin mengembalikan salah satunya (element atau status) maka dapat diisikan salah satu variablenya dengan blank_identifier.

Memperbaharui Nilai

Untuk melakukan pembaharuan nilai sama seperti slice dan array kita panggilkan key yang ingin di pembaharui lalu assign dengan nilai terbaru

package main

import "fmt"

func main() {
	stokSayur := map[string]int{
		"buncis": 30,
		"tauge":  42,
		"kol":    33,
		"selada": 45,
	}
	fmt.Println(stokSayur)
	fmt.Println("akses nilai selada: ", stokSayur["selada"])

	//melakukan update key selada
	stokSayur["selada"] = 25
	fmt.Println(stokSayur)
	fmt.Println("akses nilai selada: ", stokSayur["selada"])
}
output:
map[buncis:30 kol:33 selada:45 tauge:42]
akses nilai selada:  45
map[buncis:30 kol:33 selada:25 tauge:42]
akses nilai selada:  25

Menghapus key

Untuk menghapus key beserta nilainya dapat gunakan function yang disediakan oleh Go yaitu delete, function tersebut membutuhkan dua parameter yaitu delete(m map[[Type], key [Type], dimana m dengan tipe data map dan key dengan tipe datanya.

package main

import "fmt"

func main() {
	stokSayur := map[string]int{
		"buncis": 30,
		"tauge":  42,
		"kol":    33,
		"selada": 45,
	}
	delete(stokSayur, "kol") //penghapusan key
	fmt.Println(stokSayur)

	//pengecekan key
	element, status := stokSayur["kol"]
	fmt.Println(element, status)

}
output:
map[buncis:30 selada:45 tauge:42]
0 false

Struct (Menyusul setelah postingan tentang pointer)


Referensi