go学习笔记map部分_qq_41032328的博客-爱代码爱编程
Go学习笔记
map 是一种特殊的数据结构:一种元素对 (pair) 的无序集合,pair 的一个元素是 key,对应的另一个元素是 value,所以这个结构也称为关联数组或字典。这是一种快速寻找值的理想结构:给定 key,对应的 value 可以迅速定位。
声明和初始化方法
声明方法
在声明的时候不需要知道 map 的长度,map 是可以动态增长的。未初始化的 map 的值是 nil。
var map1 map[keytype]valuetype
var map1 map[string]int
key 可以是任意可以用 == 或者 != 操作符比较的类型,比如 string、int、float32(64)。所以数组、切片和结构体不能作为 key (译者注:含有数组切片的结构体不能作为 key,只包含内建类型的 struct 是可以作为 key 的),但是指针和接口类型可以。如果要用结构体作为 key 可以提供 Key() 和 Hash() 方法,这样可以通过结构体的域计算出唯一的数字或者字符串的 key。
初始化方法
var map1 = make(map[keytype]valuetype)
map1 := make(map[keytype]valuetype)
map1 :=map[int]string{1:"asd",2:"adas",3:"dad"}
可以使用make的第三个参数capacity定义容量
map2 := make(map[string]float32, 100)
测试键值对是否存在及删除元素
测试存在
使用下面的方法可以判断,对应的键值对是否存在
val1, isPresent = map1[key1]
isPresent 返回一个 bool 值:如果 key1 存在于 map1,val1 就是 key1 对应的 value 值,并且 isPresent 为 true;如果 key1 不存在,val1 就是一个空值,并且 isPresent 会返回 false。
删除元素
直接 delete(map1, key1) 就可以。
如果 key1 不存在,该操作不会产生错误。
map的for range操作
for key, value := range map1 {
...
}
注意 map 不是按照 key 的顺序排列的,也不是按照 value 的序排列的。
译者注:map 的本质是散列表,而 map 的增长扩容会导致重新进行散列,这就可能使 map 的遍历结果在扩容前后变得不可靠,Go 设计者为了让大家不依赖遍历的顺序,每次遍历的起点–即起始 bucket 的位置不一样,即不让遍历都从某个固定的 bucket0 开始,所以即使未扩容时我们遍历出来的 map 也总是无序的。
练习 8.1 map_days.go
创建一个 map 来保存每周 7 天的名字,将它们打印出来并且测试是否存在 “Tuesday” 和 “Hollyday”。
package main
import "fmt"
func main() {
week := map[string]int{"Monday": 1, "Tuesday": 2, "Wednesday": 3, "Thursday": 4, "Friday": 5, "Saturday": 6, "Sunday": 7}
fmt.Print(week, "\n")
for key, value := range week {
if key == "Tuesday" {
fmt.Print(value, "Tuesday存在\n")
} else if key == "Hollyday" {
fmt.Print(value, "Hollyday存在\n")
} else {
fmt.Print("不存在\n")
}
}
}
结果:
map的切片
假设我们想获取一个 map 类型的切片,我们必须使用两次 make() 函数,第一次分配切片,第二次分配切片中每个 map 元素
items := make([]map[int]int, 5)
for i:= range items {
items[i] = make(map[int]int, 1)
items[i][1] = 2
}
map 的排序
如果你想为 map 排序,需要将 key(或者 value)拷贝到一个切片,再对切片排序
package main
import (
"fmt"
"sort"
)
var (
barVal = map[string]int{"alpha": 34, "bravo": 56, "charlie": 23,
"delta": 87, "echo": 56, "foxtrot": 12,
"golf": 34, "hotel": 16, "indio": 87,
"juliet": 65, "kili": 43, "lima": 98}
)
func main() {
fmt.Println("unsorted:")
for k, v := range barVal {
fmt.Printf("Key: %v, Value: %v / ", k, v)
}
keys := make([]string, len(barVal))
i := 0
for k, _ := range barVal {
keys[i] = k
i++
}
sort.Strings(keys)
fmt.Println()
fmt.Println("sorted:")
for _, k := range keys {
fmt.Printf("Key: %v, Value: %v / ", k, barVal[k])
}
}
map键值对调
如果 map 的值类型可以作为 key 且所有的 value 是唯一的,那么通过下面的方法可以简单的做到键值对调
package main
import (
"fmt"
)
var (
barVal = map[string]int{"alpha": 34, "bravo": 56, "charlie": 23,
"delta": 87, "echo": 56, "foxtrot": 12,
"golf": 34, "hotel": 16, "indio": 87,
"juliet": 65, "kili": 43, "lima": 98}
)
func main() {
invMap := make(map[int]string, len(barVal))
for k, v := range barVal {
invMap[v] = k
}
fmt.Println("inverted:")
for k, v := range invMap {
fmt.Printf("Key: %v, Value: %v / ", k, v)
}
}
练习 8.2 map_drinks.go
构造一个将英文饮料名映射为法语(或者任意你的母语)的集合;先打印所有的饮料,然后打印原名和翻译后的名字。接下来按照英文名排序后再打印出来。
package main
import (
"fmt"
"sort"
)
func main() {
drink := map[string]string{"可乐": "cola", "雪碧": "xuebi", "红牛": "redmer", "脉动": "maidong", "冰红茶": "blacktea"}
for _, value := range drink {
fmt.Print(value, "\n")
}
for key, value := range drink {
fmt.Print(key, ":", value, "\n")
}
sl := make([]string, len(drink))
i := 0
for _, value := range drink {
sl[i] = value
i++
}
sort.Strings(sl)
for _, value := range sl {
fmt.Print(value, "\n")
}
}