22. Slice — Solusi PR

File solusi .go ada di exercises/22/homework/solutions/.

Soal 1 — Game favorit

Soal. Cetak daftar bernomor memakai range.

Cara berpikir. range memberimu posisi (mulai dari 0) dan nilai. Susun setiap baris dari posisi ditambah 1, titik, spasi, dan nilainya.

Solusi yang dikerjakan.

package main

import "fmt"

func main() {
    games := []string{"Minecraft", "Terraria", "Stardew Valley", "Hades", "Tetris"}

    for i, name := range games {
        fmt.Printf("%d. %s\n", i+1, name)
    }
}

Output:

1. Minecraft
2. Terraria
3. Stardew Valley
4. Hades
5. Tetris

Kesalahan umum.

  • Mencetak i dan mendapat 0. Minecraft. Cetak i+1.
  • Memakai for i := 0; i < len(games); i++ lalu games[i]. Itu berjalan, tetapi range lebih langsung.

Soal 2 — Jumlahkan slice

Soal. Jumlahkan semua angka dalam slice, dan cetak totalnya.

Cara berpikir. Pola akumulasi dari Bab 20: simpan total berjalan, dan perbarui di dalam perulangan. Posisi tidak dibutuhkan, jadi tulis _.

Solusi yang dikerjakan.

package main

import "fmt"

func main() {
    scores := []int{12, 7, 24, 9, 30}

    total := 0
    for _, score := range scores {
        total += score
    }

    fmt.Println("Total:", total)
}

Output:

Total: 82

Kesalahan umum.

  • Lupa menulis total := 0 sebelum perulangan. Go berhenti dengan undefined: total.

Soal 3 — Sisip dan hapus

Soal. Lakukan empat operasi slice, dan cetak slice setelah setiap operasi.

Cara berpikir. Tulis fungsi cetak kecil sekali, dan panggil setelah setiap langkah. Setiap operasi lalu cukup satu baris. Slice diberikan sebagai argumen, dan %-18s dari Bab 14 meluruskan labelnya.

Solusi yang dikerjakan.

package main

import "fmt"

func show(label string, items []string) {
    fmt.Printf("%-18s %v\n", label, items)
}

func main() {
    items := []string{"apple", "banana", "cherry"}

    show("Start", items)

    items = append(items, "date")
    show("After append", items)

    items = append([]string{"apricot"}, items...)
    show("After insert at 0", items)

    items = items[:len(items)-1]
    show("After remove last", items)

    items = append(items[:1], items[2:]...)
    show("After remove at 1", items)
}

Output:

Start              [apple banana cherry]
After append       [apple banana cherry date]
After insert at 0  [apricot apple banana cherry date]
After remove last  [apricot apple banana cherry]
After remove at 1  [apricot banana cherry]

Kesalahan umum.

  • Menulis append(items, "date") sendirian di satu baris. Go berhenti dengan append(items, "date") (value of type []string) is not used. Tugaskan hasilnya kembali.
  • Menulis items[1] = "" alih-alih menghapus posisinya. Itu meninggalkan string kosong di dalam slice.
  • Tertukar posisi di append(items[:1], items[2:]...). Bagian pertama berhenti sebelum posisi 1, dan bagian kedua mulai setelahnya.

Tantangan — Balik slice

Soal. reverse mengembalikan slice baru, dan aslinya tidak berubah.

Cara berpikir. Buat slice baru di dalam fungsi. Telusuri aslinya dari terakhir ke pertama dengan for tiga bagian, tambahkan setiap nilai ke slice baru, lalu kembalikan. Slice kosong tidak butuh kasus khusus, karena isi perulangannya tidak pernah berjalan.

Solusi yang dikerjakan.

package main

import "fmt"

func reverse(items []string) []string {
    result := []string{}
    for i := len(items) - 1; i >= 0; i-- {
        result = append(result, items[i])
    }
    return result
}

func main() {
    fruits := []string{"apple", "banana", "cherry"}
    fmt.Println(fruits) // [apple banana cherry]

    backwards := reverse(fruits)
    fmt.Println(backwards) // [cherry banana apple]
    fmt.Println(fruits)    // [apple banana cherry]

    fmt.Println(reverse([]string{})) // []
}

Bab 24 menunjukkan slices.Reverse, yang mengerjakan tugas ini di pustaka standar. Perulangan di atas gunanya untuk memahami cara kerjanya.

Kesalahan umum.

  • Mengubah items langsung alih-alih membuat slice baru. Fungsi berbagi item dengan pemanggilnya, jadi aslinya ikut berubah, dan soalnya mengatakan tidak boleh:
func reverseWrong(items []string) []string {
    for i := 0; i < len(items)/2; i++ {
        last := len(items) - 1 - i
        items[i], items[last] = items[last], items[i]
    }
    return items
}

func main() {
    fruits := []string{"apple", "banana", "cherry"}
    backwards := reverseWrong(fruits)
    fmt.Println(backwards) // [cherry banana apple]
    fmt.Println(fruits)    // [cherry banana apple]
}
  • Memulai perulangan dari len(items). Posisi itu tidak ada, dan program crash dengan panic: runtime error: index out of range [3] with length 3. Mulai dari len(items) - 1, dan lanjutkan selama i >= 0.

Selesai?

Bab berikutnya mengajarkan map, yang mencari nilai berdasarkan nama, bukan posisi.