iT邦幫忙

2023 iThome 鐵人賽

DAY 16
0
Modern Web

起步Go!Let's Go!系列 第 16

[ Day 16] Go 映射 (Map) :鍵值之間的奇幻冒險

  • 分享至 

  • xImage
  •  

Go 映射 Map

在 Go 中,Map 是 key-value 的組合,但 Map 所有的 Key 的資料型態都必須一樣;Value 的資料型態也必須相同。另外再跟設值與取值需要使用 [] 而不是 .,Map 的 zero value 會是 nil

宣告 Map

宣告 Map 有多種方式,先從最基本的開始學起吧!

package main
import "fmt"
func main(){
    price := make(map[string]int)
    fmt.Println(price)
}

執行結果:
map[]

這樣就成功宣告了一個空 Map。接著,代 keyvalue 進去。

package main
import "fmt"
func main(){
    price := make(map[string]int)  // make 像是 Ruby 的 new
    price["apple"] = 20
    price["kiwi"] = 34
    price["berry"] = 58
    fmt.Println(price)
    
}

執行結果:
map[apple:20 berry:58 kiwi:34]

這樣就建立了一個有 key-value 的 Map。
這種結構 Go 稱它為 Map,Javascript 稱為 Object,Ruby 稱為 Hash,Python 稱為 Dictionary,雖然名稱不一樣,但都是類似的東西。

另一種宣告方式

除了上面的宣告方式,還可以用比較簡短的宣告方式,這樣更符合工程師的氣質。

package main
import "fmt"
func main(){
    price := map[string]int{
        "apple" : 20,
        "kiwi" : 38,
        "berry" : 58,
    }
    fmt.Println(price)
    fmt.Println(price["kiwi"])
}

執行結果:
map[apple:20 berry:58 kiwi:34]
38

當想要看 Map 中特定 keyvalue,可以用 price["kiwi"],這樣就可以得到該 keyvalue

Map 的操作

map 因為 key 本身是有資料型別的,因此只能用 [] 來設值和取值,而不是像其他程式語言使用 .,例如: Ruby 的 Hash
來看一下 Map 可以用哪些方式去操作。

查看 key-value 的數量

可以使用 len() 去取得 Map 中 key-value 的數量。

package main
import "fmt"
func main(){
    price := make(map[string]int)
    price["apple"] = 20
    price["kiwi"] = 34
    price["berry"] = 58
    price["melon"] = 69
    price["orange"] = 43
    fmt.Println(len(price))
}

執行結果:
5

刪除 delete()

除了可以新增以及取值外,當然也能刪除,我們可以使用 delete(map_name, key),這樣就可以刪除 Map 中 key 的值。

package main
import "fmt"
func main(){
    price := map[string]int{
        "apple" : 20,
        "kiwi" : 38,
        "berry" : 58,
        "melon" : 69,
        "orange" : 43,
    }
    delete(price, berry)
    fmt.Print(price)
}

執行結果:
map[apple:20 kiwi:38 melon:69 orange:43]
4

檢查 Map 中 Key 是否存在

要怎麼檢查 key 是否存在於 Map 中呢?
可以利用兩個回傳值去存取,第一個會回傳「對應的值」,第二個會回傳「布林值」用來表示該鍵是否存在。

package main
import "fmt"
func main(){
    price := map[string]int{
        "apple" : 20,
        "kiwi" : 38,
        "melon" : 69,
        "orange" : 43,
    }
    val, ok := price["kiwi"]
    fmt.Println(val,ok)
    val, ok := price["berry"]
    fmt.Println(val,ok)
}

執行結果:
38 ture
0 false

如果該 key 不存在,讀取該 value 並不會報錯,會以預設值充當對應值回傳。

如果只想確認該值是否存在,可以在回傳對應值的部分設為_,以免因為沒有宣告變數而報錯。

package main
import "fmt"
func main(){
    price := map[string]int{
        "apple" : 20,
        "kiwi" : 38,
        "melon" : 69,
        "orange" : 43,
    }
    _, ok := price["kiwi"]
    fmt.Printf("price[\"kiwi\"] 存在嗎?%t", ok)
}

執行結果:
price["kiwi"] 存在嗎?true

補充:
在最後輸出因要 print 雙引號,但是為了避免被誤認字串用的雙引號,所以可以在雙引號前加上 \ 反斜線。

在 Map 中的 range

在 Array 及 Slice 有提到可以用 range 的方式去巡迴陣列資料,Map 也可以用這種方式進行巡迴。

package main
import "fmt"
func main(){
    price := map[string]int{
        "apple" : 20,
        "kiwi" : 38,
        "melon" : 69,
        "orange" : 43,
    }
    for k, v := range price {
        fmt.Printf("%s 的價格:$%d/n", k, v)    
    }
}

執行結果:
orange的價格:$43
apple的價格:$20
kiwi的價格:$38
melon的價格:$69

在 Go 中,map 的走訪順序是不保證固定的。當你在走訪 map 時,其順序可能因為 Golang 的實現和底層資料結構而不同。
如果需要保證 map 的走訪順序,可以用其他的資料結構,例如:slice, linked list 來實現。

在 Map 使用 For Loop

利用 for loop 走訪時,通常會用 key, value 去接 range 的回傳值。
當你想要走訪 key,可以直接寫成 k := range xxx,而不用寫成 k, _ := range xxx

package main
import "fmt"
func main(){
    price := map[string]int{
        "apple" : 20,
        "kiwi" : 38,
        "melon" : 69,
        "orange" : 43,
    }
    for k := range price {
        fmt.Println(k)
    }
}

執行結果:
apple
kiwi
melon
orange

小小練習

題目一

利用迴圈印出九九乘法表

package main
import "fmt"
func main(){
    for x := 1; x <= 9; x++ {
        for y := 1; y <= 9; y++ {
            result := x * y
            fmt.Printf("%d x %d = %d\n", x, y, result)
        }
    }
}

題目二

不呼叫golang提供的排序函式下,由小到到大排序一個整數陣列

arr :=[...]int{10, 4, 5, 3, 7, 1, 9, 8}

:::spoiler 解答

package main
import "fmt"
func bubbleSort(arr){
    n := len(arr)
    for i := 0; i < n-1; i++{
        for j := 0; j < n-i-1, j++{
            if arr[j] > arr[j+1]{
                arr[j], arr[j+1] = arr[j+1], arr[j]
            }
        }
    }  
}
func main(){
    arr:=[]int{10, 4, 5, 3, 7, 1, 9, 8}
    bubbleSort(arr)
    fmt.Println(arr)
}

使用泡沫排序,就可以不使用 Go 提供的排序函式,進行排序了。
關於泡沫排序可以去找維基百科。


上一篇
[ Day 15 ] Go 切片魔法:自由改變的程式碼旋律
下一篇
[ Day 17 ] Go 方法 (Method):物件導向的契約
系列文
起步Go!Let's Go!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言