Hike News
Hike News

Go初識-day12-map類型(key-value pair)

introduction

key-value的數據結構,又名關聯數組或是hash table
在python中被稱為字典(dictionary)

  • map本身是無序的
  • map的key是唯一的
  • map為引用類型

聲明

1
var 變量名 map[key的類型]value的類型
  • 聲明是不會分配內存的,只是聲明變量為map類型而已
  • 必須初始化(make)才能使用
  • 若無初始化,表示此變量並無內存空間存放,操作會發生panic

example 1

1
2
3
4
5
var a map[string]string

var a map[string]int

var a map[int]string

example 2

1
var map[string]map[string]string
  • key為string類型
  • value為map類型

初始化

make

語法

1
變量 := make(map[key的類型]值的類型,容量)
  • 容量可以不填寫,會有一個默認map所儲存的容量值,如超過容量值,會觸發內存重新分配 (效能降低)
  • 容量值有填寫的情況下,會提前分配一個相對應容量值的內存空間 (效能較高)
  • 可根據自己的需求定義容量會獲得比較好的效能
  • 如果儲存的值一直沒有超過初始化的容量,就不會觸發內存重新分配,性能最高
1
2
var a map[string]string
a = make(map[string]string)

可簡寫成

1
a := make(map[string]string)


{}初始化

1
2
var a map[string]string
a = map[string]string{}

可簡寫成

1
a := map[string]string{}

聲明時並初始化

1
var a map[string]string = map[string]string{"1":"apple","2":"banana"}

添加鍵值對、更新鍵值

語法

1
變量[key] = value

example

1
2
3
4
5
6
7
8
9
10
11
package main

import "fmt"

func main(){
var a map[string]string = map[string]string{"1":"apple","2":"banana"}
fmt.Println("initialize",a)
a["3"] = "cake"
a["1"] = "APPLE"
fmt.Println("modify",a)
}

result

1
2
initialize map[1:apple 2:banana]
modify map[3:cake 1:APPLE 2:banana]

操作嵌套的map

  • 在對第一層key1賦值時,其value也為map類型,不要忘記將value的map類型初始化
  • 對第一層的其他key賦值時,value需再重新初始化
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    package main

    import "fmt"

    func main(){
    a := make(map[string]map[string]string)
    a["key1"]= make(map[string]string)

    //賦值
    a["key1"]["key1_1"] = "value1"
    a["key1"]["key1_2"] = "value2"

    //對第一層其他key賦值,需再重新初始化
    a["key2"] = make(map[string]string)

    //才能賦值
    a["key2"]["key2_1"] = "value3"

    //覺得以上稍嫌麻煩
    //你可以直接使用{}方法直接多個賦值
    a["key3"] = map[string]string{"key3_1":"value4","key3_2":"value5"}


    fmt.Println(a)
    }

result

1
map[key1:map[key1_1:value1 key1_2:value2] key2:map[key2_1:value3] key3:map[key3_1:value4 key3_2:value5]]

查找操作

查找對應的key是不是在map

語法

1
value,ok := name[key]

example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import "fmt"

func main(){
a := make(map[string]string)

a["key1"] = "value1"
a["key2"] = "value2"
a["key3"] = "value3"

value,ok := a["key4"]
fmt.Println("key4_status:",ok,"key4_value:",value)

value2,ok2 := a["key3"]
fmt.Println("key3_status:",ok2,"key3_value:",value2)
}

result

1
2
key4_status: false key4_value: 
key3_status: true key3_value: value3
  • 要是key存在於map類型的name
    ok會返回truevalue會返回key對應的值

  • 要是key不存在於name
    ok會返回falsevalue為空


遍歷

使用for range遍歷

example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import "fmt"

func main(){
a := make(map[string]string)

a["key1"] = "value1"
a["key2"] = "value2"
a["key3"] = "value3"

for k,v := range a {
fmt.Println(k,":",v)
}
}

result

1
2
3
key1 : value1
key2 : value2
key3 : value3

刪除 (delete)

刪除map中的鍵使用delete內置函數刪除
語法: delete(map,key)

example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import "fmt"

func main(){
a := make(map[string]string)

a["key1"] = "value1"
a["key2"] = "value2"
a["key3"] = "value3"

delete(a,"key1") //*

fmt.Println(a)
}

result

1
map[key2:value2 key3:value3]

求長度

求map的長度使用len(map)

example

1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import "fmt"

func main(){
a := make(map[string]string)

a["key1"] = "value1"
a["key2"] = "value2"
a["key3"] = "value3"

fmt.Println("length of map:",len(a))
}

result

1
length of map: 3

map為引用類型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import "fmt"

func modify_map(aa map[string]string){
aa["key1"] = "VALUE_ONE" //*
}

func main(){
a := make(map[string]string)

a["key1"] = "value1"
a["key2"] = "value2"
a["key3"] = "value3"

fmt.Println("Before Modify:")
fmt.Println(a)

modify_map(a) //*

fmt.Println("Afer Modify:")
fmt.Println(a)
}

result

1
2
3
4
Before Modify:
map[key3:value3 key1:value1 key2:value2]
Afer Modify:
map[key1:VALUE_ONE key2:value2 key3:value3]

map類型的切片是允許的

比較少人使用

example 1

1
2
3
4
5
6
7
8
9
10
package main

import "fmt"

type m map[int]string //[1]

func main(){
a := []map[int]string{m{1:"A"},m{2:"B"},m{3:"C"}}
fmt.Println(a)
}

[1] 使用typemap[int]string類型取一個為m的別名

result

1
[map[1:A] map[2:B] map[3:C]]

example 2

1
2
3
4
5
6
7
8
9
10
11
12
package main

import "fmt"

func main(){
a := make([]map[int]string,3) //[1]
for i:=1;i<=3;i++ {
a[i-1] = make(map[int]string) //[2]
a[i-1][i] = string('A'+i-1)
}
fmt.Println(a)
}

[1] 用make初始化一切片
[2] 搭配for循環將切片裡map類型的元素 逐一使用make初始化

result

1
[map[1:A] map[2:B] map[3:C]]

map中的排序

  • map中的key是無序的
  • 並沒有函數可以直接傳入map類型進行排序
  1. 先獲取map所有key,把key進行排序
  2. 按照排序好的key對map進行遍歷
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package main

import (
"fmt"
"sort"
)

func traversal(key_list []string,m map[string]string){
for _,v := range key_list{
fmt.Println(v,"-",m[v])
}
}

func map_key_sort(aa map[string]string)[]string{
slice := make([]string,0)
for k,_ := range aa {
slice = append(slice,k)
}
sort.Strings(slice)
return slice
}

func main(){
a := make(map[string]string)

a["key1"] = "value9"
a["key2"] = "value8"
a["key3"] = "value7"
a["key7"] = "value6"
a["key9"] = "value5"
a["key8"] = "value4"
a["key6"] = "value3"
a["key4"] = "value2"
a["key5"] = "value1"

key_list := map_key_sort(a)
traversal(key_list,a)
}

result

1
2
3
4
5
6
7
8
9
key1 - value9
key2 - value8
key3 - value7
key4 - value2
key5 - value1
key6 - value3
key7 - value6
key8 - value4
key9 - value5

map反轉 (鍵值互換)

初始化另一個map將key及value互換即可

  • 新初始化的map其key與value的類型也必須相反
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import (
"fmt"
)

func key_value_change(source map[int]string)map[string]int{
target := make(map[string]int)
for k,v := range source {
target[v] = k
}
return target
}

func main(){
a := make(map[int]string)
a[1] = "value1"
a[2] = "value2"
a[3] = "value3"

trans := key_value_change(a)
fmt.Println(trans)
}

result

1
map[value3:3 value1:1 value2:2]