字典map
哈希表是一种巧妙并且实用的数据结构,它是一个无序的key/value对的集合。在Go语言中,一个map就是一个哈希表的引用,map类型可以写为map[K]V, 其中K和V分别对应key和value。
创建空map的方式:
var a = make(map[string]int)
var b = map[string]int{}
用map字面值的语法创建map:
ages := map[string]int{
"alice": 31,
"charlie": 34,
}
// 2个效果等同
ages := make(map[string]int)
ages["alice"] = 31
ages["charlie"] = 34
使用内置的delete函数可以删除元素:
delete(ages, "alice")
如果一个map查找失败将返回value类型对应的零值:
fmt.Println(ages["zzz"]) //0
x += y 和 x++ 等简短赋值语法也可以用在map上:
ages["bob"] = ages["bob"] + 1
ages["bob"] += 1
ages["bob"]++
map中的元素并不是一个变量, 因此我们不能对map的元素进行取址操作,禁止对map元素取址的原因是map可能随着元素数量的增长而重新分配更大的内存空间, 从而可能导致之前的地址无效。
map类型的零值是nil, 也就是没有引用任何哈希表:
var c map[string]int
fmt.Println(c == nil) // "true"
fmt.Println(len(ages) == 0)
查找一个key是否存在,因为如果key不存在, 直接读取将得到value对应类型的零值,所以我们可以这样做:
age, ok := ages["bob"]
if !ok {
/* "bob" is not a key in this map; age == 0. */
}
// 你会经常看到将这两个结合起来使用
if age, ok := ages["bob"]; !ok { /* ... */ }
if age, ok := ages["zhexiao"]; !ok{
fmt.Println("没找到")
}else{
fmt.Println(age)
}
Map的value类型也可以是一个聚合类型, 比如是一个map或slice:
var graph = make(map[string]map[string]bool)
// demo
var a = make(map[string]map[int]string)
func main() {
b := make(map[int]string)
b[123] = "home"
a["zhexiao"] = b
fmt.Println(a["zhexiao"][123])
}
有时候需要一个map或set的key是slice类型,但是map的key必须是可比较的类型,明显slice类型是不可比较的。但是我们可以通过两个步骤绕过这个限制:
1. 定义一个辅助函数k, 将map的key从slice类型转为string类型
2. 创建一个map,key为string类型的,每次对map操作时先用辅助函数k将slice转为string类型
var m = make(map[string]int)
func k(list []string) string {
return fmt.Sprintf("%q", list)
}
func add(list []string) {
m[k(list)]++
}
func count(list []string) int {
return m[k(list)]
}
func main() {
a := []string{"zhe", "xiao"}
add(a)
add(a)
add(a)
fmt.Println(count(a)) //3
fmt.Println(m) //map[["zhe" "xiao"]:3]
fmt.Println(m["[\"zhe\" \"xiao\"]"]) //3
}