在 Go 中,Map 是 key-value 的組合,但 Map 所有的 Key 的資料型態都必須一樣;Value 的資料型態也必須相同。另外再跟設值與取值需要使用 []
而不是 .
,Map 的 zero value 會是 nil
。
宣告 Map 有多種方式,先從最基本的開始學起吧!
package main
import "fmt"
func main(){
price := make(map[string]int)
fmt.Println(price)
}
執行結果:
map[]
這樣就成功宣告了一個空 Map。接著,代 key
和 value
進去。
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 中特定 key
的 value
,可以用 price["kiwi"]
,這樣就可以得到該 key
的 value
。
map 因為 key 本身是有資料型別的,因此只能用 []
來設值和取值,而不是像其他程式語言使用 .
,例如: Ruby 的 Hash
。
來看一下 Map 可以用哪些方式去操作。
可以使用 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(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
要怎麼檢查 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 雙引號,但是為了避免被誤認字串用的雙引號,所以可以在雙引號前加上\
反斜線。
在 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 來實現。
利用 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 提供的排序函式,進行排序了。
關於泡沫排序可以去找維基百科。