iT邦幫忙

2025 iThome 鐵人賽

DAY 3
0
Modern Web

後端攻略筆記系列 第 3

Day 3 : Go語言 slice 與 map 應用練習

  • 分享至 

  • xImage
  •  

📘 小劇場:雜貨店老闆的日常

你是一位經營「Gross 雜貨舖」的小老闆,店裡有一份 Units 表,記錄各種單位轉換(像 dozen, gross 等)。顧客每天都會來買東西,你需要用程式來幫自己管理帳單。


應用題(5 題)

第 1 題:
第一位顧客走進來說:「我要 1 打蘋果 (dozen)。」
請使用 NewBill 建立一個新的帳單,並用 AddItem 將蘋果加進去。
👉 請寫出呼叫程式的片段,最後 bill["apple"] 應該是多少?


第 2 題:
第二位顧客說:「我還想要半打香蕉 (half_of_a_dozen)。」
在同一張帳單上,加進香蕉。
👉 請寫出呼叫 AddItem 的程式片段。最後 bill["banana"] 的值是多少?


第 3 題:
突然,顧客說:「啊!我錯了,蘋果我要少一打,幫我退掉!」
👉 請你設計 RemoveItem 函式,能夠把指定的數量從帳單扣掉。如果某樣東西變成 0,要順便刪除這個鍵。
(例如:RemoveItem(bill, units, "apple", "dozen"),結果 bill 裡應該不再有 "apple"。)


第 4 題:
下一位顧客問你:「我帳單上有多少香蕉?」
👉 請你實作 GetItem 函式,能夠回傳某個商品的數量,並判斷是否存在。
(例如:GetItem(bill, "banana") 應該回傳數量以及 true。)


第 5 題(進階挑戰):
有一位大客人說:「幫我準備 1 great_gross 的雞蛋!」
👉 請在同一張帳單中加上雞蛋,並計算此時帳單總共有多少件商品(加總所有值)。
請寫出迴圈累加 bill 的程式片段,並算出總數。



📘 「Gross 雜貨舖小劇場」應用題詳解


第 1 題

顧客要「1 打蘋果 (dozen)」。

✅ 解題思路:

  1. 先建一張新帳單 NewBill()
  2. 使用 AddItem 把 1 dozen 的蘋果加入。
  3. dozen = 12,所以 bill["apple"] == 12
bill := NewBill()
units := Units()

AddItem(bill, units, "apple", "dozen")
fmt.Println(bill["apple"]) // 12

👉 答案: bill["apple"] = 12


第 2 題

顧客又要「半打香蕉 (half_of_a_dozen)」。

✅ 解題思路:

  1. 繼續在同一張帳單上加香蕉。
  2. half_of_a_dozen = 6。
AddItem(bill, units, "banana", "half_of_a_dozen")
fmt.Println(bill["banana"]) // 6

👉 答案: bill["banana"] = 6


第 3 題

顧客後悔了,要退「一打蘋果」。

✅ 解題思路:

  1. 我們要自己實作 RemoveItem
  2. 移除時,用跟 AddItem 一樣的邏輯,但數量改成減掉。
  3. 如果數量減到 0 或以下,要把該商品從帳單刪除。
func RemoveItem(bill, units map[string]int, item, unit string) bool {
    qty, ok := units[unit]
    if !ok {
        return false
    }
    current, exists := bill[item]
    if !exists {
        return false // 帳單根本沒這東西
    }
    if current < qty {
        return false // 沒有那麼多可以扣
    }
    if current == qty {
        delete(bill, item) // 剛好扣光
    } else {
        bill[item] -= qty
    }
    return true
}

測試:

RemoveItem(bill, units, "apple", "dozen")
fmt.Println(bill) // banana 還在,apple 消失

👉 答案: "apple" 被刪除,帳單只剩 "banana": 6


第 4 題

顧客想查詢「香蕉數量」。

✅ 解題思路:

  1. 實作 GetItem
  2. 如果 item 存在,回傳數量與 true;否則回傳 0, false
func GetItem(bill map[string]int, item string) (int, bool) {
    qty, ok := bill[item]
    if !ok {
        return 0, false
    }
    return qty, true
}

測試:

qty, ok := GetItem(bill, "banana")
fmt.Println(qty, ok) // 6 true

👉 答案: 會輸出 6 true


第 5 題(進階挑戰)

顧客要「1 great_gross 的雞蛋」,再算出整張帳單的總件數。

✅ 解題思路:

  1. great_gross = 1728。
  2. 加進 eggs
  3. 用迴圈加總 bill map 的所有值。
AddItem(bill, units, "egg", "great_gross")

total := 0
for _, qty := range bill {
    total += qty
}
fmt.Println("Total items:", total)

假設目前帳單還有:

  • banana = 6
  • egg = 1728

👉 答案: Total items = 1734


若將上面每題寫在一起將會是下方程式碼

📦 完整程式碼 (含 main)

package main

import (
        "fmt"
)

// -----------------------------
// 題目給的基礎函式
// -----------------------------
func Units() map[string]int {
        return map[string]int{
                "quarter_of_a_dozen": 3,
                "half_of_a_dozen":    6,
                "dozen":              12,
                "small_gross":        120,
                "gross":              144,
                "great_gross":        1728,
        }
}

func NewBill() map[string]int {
        return map[string]int{}
}

func AddItem(bill, units map[string]int, item, unit string) bool {
        qty, ok := units[unit]
        if !ok {
                return false
        }
        bill[item] += qty
        return true
}

// -----------------------------
// 題目第 3~4 題要自己補完的函式
// -----------------------------

// 移除商品數量
func RemoveItem(bill, units map[string]int, item, unit string) bool {
        qty, ok := units[unit]
        if !ok {
                return false
        }
        current, exists := bill[item]
        if !exists {
                return false
        }
        if current < qty {
                return false
        }
        if current == qty {
                delete(bill, item)
        } else {
                bill[item] -= qty
        }
        return true
}

// 查詢商品數量
func GetItem(bill map[string]int, item string) (int, bool) {
        qty, ok := bill[item]
        if !ok {
                return 0, false
        }
        return qty, true
}

// -----------------------------
// 主程式 (整合呼叫)
// -----------------------------
func main() {
        units := Units()
        bill := NewBill()

        // 第 1 題:加入一打蘋果
        fmt.Println("== 第 1 題 ==")
        AddItem(bill, units, "apple", "dozen")
        fmt.Println("apple:", bill["apple"]) // 12

        // 第 2 題:加入半打香蕉
        fmt.Println("== 第 2 題 ==")
        AddItem(bill, units, "banana", "half_of_a_dozen")
        fmt.Println("banana:", bill["banana"]) // 6
        fmt.Println("bill:", bill)

        // 第 3 題:退回一打蘋果
        fmt.Println("== 第 3 題 ==")
        RemoveItem(bill, units, "apple", "dozen")
        fmt.Println("bill after removing apple:", bill) // apple 應該消失

        // 第 4 題:查詢香蕉
        fmt.Println("== 第 4 題 ==")
        qty, ok := GetItem(bill, "banana")
        fmt.Println("banana exists?", ok, "qty:", qty)

        // 第 5 題:加入一 great_gross 雞蛋,並計算總件數
        fmt.Println("== 第 5 題 ==")
        AddItem(bill, units, "egg", "great_gross")
        total := 0
        for _, qty := range bill {
                total += qty
        }
        fmt.Println("bill:", bill)
        fmt.Println("Total items:", total) // 1734
}

📝 執行流程 & 預期輸出

執行 go run main.go 後,輸出會大概像這樣:

== 第 1 題 ==
apple: 12
== 第 2 題 ==
banana: 6
bill: map[apple:12 banana:6]
== 第 3 題 ==
bill after removing apple: map[banana:6]
== 第 4 題 ==
banana exists? true qty: 6
== 第 5 題 ==
bill: map[banana:6 egg:1728]
Total items: 1734

這樣就是一份 完整可執行的範例程式,直接跑就能驗證每一題的答案。


上一篇
Day 2 : Go語言 slice 與 map 進階理解
下一篇
Day 4 : Go語言 slice 與 map - 延伸練習HW
系列文
後端攻略筆記13
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言