Vec (Vector) — Rust

Vec (Vector) di Rust Vec adalah dynamic array di Rust — bisa bertambah dan berkurang ukurannya. Ini adalah koleksi paling umum digunakan. Membuat Vector //…

Vec<T> (dibaca vector) adalah daftar yang panjangnya bisa bertambah dan berkurang saat program jalan, dengan semua isinya bertipe sama (T). Bayangin paku nota di dapur Kedai Martabak Bang Rusdi. Tiap pesanan baru ditusukkan di ujung, nota paling ujung bisa dicabut lagi, dan jumlahnya berubah sepanjang hari. Beda dengan papan harga menu, yang dicetak sekali dengan tepat tiga harga. Papan harga itu array ([u32; 3], panjangnya tetap), paku nota itu Vec<u32>.

🧪 Tebakan cepat: ada tiga pesanan hari ini, lalu kasir membaca pesanan nomor 3:

let pesanan = vec![102000, 70000, 38000];
println!("{}", pesanan[3]);

Lolos compile? Kalau iya, apa yang tercetak? Tebak dulu, jawabannya ada di bagian "Membaca isi: [i] atau .get(i)".

Membuat Vec dan menambah isi

fn main() {
    let mut pesanan: Vec<u32> = Vec::new();
    pesanan.push(102000);
    pesanan.push(70000);
    pesanan.push(38000);
    println!("{:?}", pesanan);
    println!("Jumlah pesanan: {}", pesanan.len());

    let harga = vec![32000, 38000, 5000];
    println!("{:?}", harga);
}
[102000, 70000, 38000]
Jumlah pesanan: 3
[32000, 38000, 5000]

Kalau mut-nya lupa, push ditolak:

error[E0596]: cannot borrow `pesanan` as mutable, as it is not declared as mutable
 --> src/main.rs:3:5
  |
3 |     pesanan.push(102000);
  |     ^^^^^^^ cannot borrow as mutable
  |
help: consider changing this to be mutable
  |
2 |     let mut pesanan: Vec<u32> = Vec::new();
  |         +++

Membaca isi: [i] atau .get(i)

Isi Vec bernomor mulai dari 0, sama seperti array. Ada dua cara membacanya:

fn main() {
    let pesanan = vec![102000, 70000, 38000];
    println!("{}", pesanan[0]);
    println!("{:?}", pesanan.get(1));
    println!("{:?}", pesanan.get(3));
    println!("{}", pesanan[3]);
}
$ cargo run
   Compiling kedai v0.1.0 (/home/kamu/kedai)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.16s
     Running `target/debug/kedai`
102000
Some(70000)
None

thread 'main' (23382854) panicked at src/main.rs:6:27:
index out of bounds: the len is 3 but the index is 3
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

push, pop, sort, dan sum

fn main() {
    let mut pesanan = vec![102000, 70000, 38000];
    pesanan.push(45000);
    println!("{:?} len {}", pesanan, pesanan.len());
    let terakhir = pesanan.pop();
    println!("{:?}", terakhir);
    pesanan.sort();
    println!("{:?}", pesanan);
    let total: u32 = pesanan.iter().sum();
    println!("Total hari ini: {}", total);
    for p in &pesanan {
        println!("Pesanan: {}", p);
    }
}
[102000, 70000, 38000, 45000] len 4
Some(45000)
[38000, 70000, 102000]
Total hari ini: 210000
Pesanan: 38000
Pesanan: 70000
Pesanan: 102000
Langkah Isi pesanan sesudahnya len()
vec![102000, 70000, 38000] [102000, 70000, 38000] 3
push(45000) [102000, 70000, 38000, 45000] 4
pop(), hasilnya Some(45000) [102000, 70000, 38000] 3
sort() [38000, 70000, 102000] 3

Slice: sebagian Vec

fn main() {
    let pesanan = vec![102000, 70000, 38000, 45000];
    let tengah = &pesanan[1..3];
    println!("{:?}", tengah);
    let total: u32 = tengah.iter().sum();
    println!("{}", total);
}

Output-nya [70000, 38000] lalu 108000. &pesanan[1..3] adalah slice: pinjaman ke sebagian isi, dari nomor 1 sampai sebelum 3, sama seperti range di for. Tipenya &[u32]. Gak ada yang disalin, slice cuma menunjuk ke isi Vec aslinya.

Vec berisi String dan ownership

Vec juga bisa berisi teks String. Bedanya dengan angka: push memindahkan String-nya ke dalam Vec.

fn main() {
    let mut antrean: Vec<String> = Vec::new();
    let nota = String::from("Martabak telur");
    antrean.push(nota);
    println!("{}", nota);
}
error[E0382]: borrow of moved value: `nota`
 --> src/main.rs:5:20
  |
3 |     let nota = String::from("Martabak telur");
  |         ---- move occurs because `nota` has type `String`, which does not implement the `Copy` trait
4 |     antrean.push(nota);
  |                  ---- value moved here
5 |     println!("{}", nota);
  |                    ^^^^ value borrowed here after move
  |
help: consider cloning the value if the performance cost is acceptable
  |
4 |     antrean.push(nota.clone());
  |                      ++++++++

Notanya sekarang milik antrean. Baca lewat Vec-nya, antrean[0], atau push salinannya dengan nota.clone() kalau nota masih perlu dipakai.

📌 Kapasitas

Di balik layar, Vec memesan tempat lebih dari yang dipakai, supaya push gak perlu pindah tempat tiap kali. len() adalah isi yang dipakai, capacity() tempat yang sudah dipesan. Vec::with_capacity(100) memesan tempat 100 isi sejak awal: len() 0, capacity() 100. Berguna kalau kamu sudah tahu kira-kira berapa isinya.

⚠️ Jebakan yang sering ketemu

TL;DR: Vec<T> adalah daftar setipe yang panjangnya bisa berubah: buat dengan Vec::new() atau vec![...], dan variabelnya let mut kalau isinya diubah. push menambah di ujung, pop mencabut dari ujung (Some(x) atau None), sort mengurutkan, len menghitung, iter().sum() menjumlah (tulis tipenya). v[i] panic kalau di luar batas (index out of bounds: the len is 3 but the index is 3), v.get(i) memberi Some atau None. Cetak dengan {:?}. &v[1..3] adalah slice, pinjaman ke nomor 1 dan 2. push memindahkan String ke dalam Vec.

Yang akan kamu pelajari