数据类型之map
章节
- map
- map声明及初始化
- map嵌套
- map增删改查
- map迭代
- map排序
一、map
map是由键值对组成的无序集合,类似于其它语言中的字典或hashmap,主要特性:
- 引用类型,可以通过make函数创建map、可以嵌套
- map的键必须是支持 == 或 != 比较运算的类型 ( 如int、string、float、指针和类型 ) 等,值可以是任何类型
- map的初始值为nil,只有经过初始化的map才能操作
- 通过for-range组合迭代map,但map是无序的
- 通过key操作map、delete函数删除key、len函数获取map的长度
- map是不能比较的
二、map声明及初始化
/* 声明map类型 */ var map名 map[键类型]值类型 /* 初始化map */ map名 := make(map[键类型]值类型, 可选容量) // 使用make函数初始化为一个空的map 或 map名 = map[键类型]值类型{} /* 声明并初始化map */ var map名 = map[键类型]值类型{键: 值, 键: 值, ...} map名 := map[键类型]值类型{键: 值, 键: 值, ...}
示例:
package main import "fmt" func main() { // 声明一个键类型int, 值为string类型的map var dict map[int]string // 空dict默认值为nil fmt.Println(dict == nil) // 输出ture // 没有初始化过的map不能操作 dict[1] = "a" // 编译错误 // 通过make函数创建并初始化出一个空map d := make(map[int]string) fmt.Println(d) // 输出 map[] // 声明与初始化map并指定键值(字面量) d1 := map[int]string{1: "a", 2: "b", 3: "c", 4: "d"} var d2 = map[string]int{"a": 1, "b": 2, "c": 3, "d": 4} fmt.Println(d1) // 输出: map[1:a 2:b 3:c 4:d] fmt.Println(d2) // 输出: map[a:1 b:2 c:3 d:4] }
通过内置的len函数获取map的key个数
package main import ( “fmt” ) func main() { map1 := map[string]int{"one": 1, "two": 2, "three": 3} fmt.Println(len(map1)) // 输出:3 }
三、map嵌套
map是可以嵌套的
package main import "fmt" func main() { // 键类型是int, 值类型是个map d := map[int]map[int]string{ 1: map[int]string{1: "a", 2: "b", 3: "c"}, 2: map[int]string{1: "A", 2: "B", 3: "D"}, } fmt.Println(d) // map[1:map[1:a 2:b 3:c] 2:map[1:A 2:B 3:D]] fmt.Println(d[1]) // map[1:a 2:b 3:c] fmt.Println(d[1][1]) // a
四、map的增删改查
通过key操作map、 delete函数删除key
package main import ( "fmt" ) func main() { var dict map[int]string fmt.Println(dict[1]) // 编译错误,没有初始化的map不能进行任何操作 // 通过map初始化个mp dict = make(map[int]string) fmt.Println(dict) // 输出: map[] // 增 dict[1] = "Apple" dict[2] = "Banana" dict[3] = "Cherry" dict[4] = "Durian" fmt.Println(dict) // 输出: map[1:Apple 2:Banana 3:Cherry 4:Durian] // 删 通过delete函数删除key delete(dict, 1) delete(dict, 2) delete(dict, 100) // 删除一个不存在的key不会报错 fmt.Println(dict) // 输出: map[3:Cherry 4:Durian] // 改 dict[3] = "Coconut" // 修改指定的key的值 fmt.Println(dict) // 输出: map[3:Coconut 4:Durian] // 查 fmt.Println(dict[3], dict[4]) // 输出: Coconut Durian }
当要找的key不存在时,得到的是值类型的零值
package main import ( "fmt" ) // 判断key是否存在 // func main() { dict := map[int]string{1: "", 2: "two", 3: "three", 4: "four"} // 查找一个不存在的key fmt.Println(dict[5]) // 输出: 空字符串,类型的例子 }
上面的例子当获取dict[5]这个不存在键时得到是值类型的零值,也就是空字符串,这样和其它的键dict[1]的值混淆了, 可以通过下面的方式
package main import ( "fmt" ) func main() { dict := map[int]string{1: "", 2: "two", 3: "three", 4: "four"} // 当key存在时,实际是返回两个值,一个是键对应的值,一个是bool值(true) value, ok := dict[2] fmt.Println(value, ok) // 输出:two true if ok { fmt.Println(value) // 输出:two } // 当key不存在时,返回两个值,一个是值类型的零值,一个是bool值(false) val, exist := dict[100] fmt.Println(val, exist) // 输出: false if exist { // 不会执行 fmt.Println(val) } }
其实根据键获取值的时候返回的是两个值, 当键存在时返回的是对应的值和true,否则返回的零值和false
五、map遍历
通过for-range组合对map进行迭代,可以得到key、value以及key-value,注意map是无序的
package main import ( "fmt" ) func main() { // 定义一个map dict := map[int]string{1: "A", 2: "B", 3: "C", 4: "D"} // 取所有的key与value fmt.Println("key-value:") for key, value := range dict { fmt.Println(key, value) } // 取所有的key fmt.Println("key:") for key := range dict { fmt.Println(key) } // 取所有的value fmt.Println("value:") for _, value := range dict { fmt.Println(value) } }
// 输出 key-value: 3 C 4 D 1 A 2 B key: 3 4 1 2 value: C D A B
// 将stduent这个map中的值大于30提取出来放到另一个(reslut)map中 func main() { result := make(map[string]int) stduent := map[string]int{ "zhangshan": 34, "lisi": 29, "wangwu": 41, "ailiu": 53, } // fmt.Println(result, stduent) for key, vaule := range stduent { if vaule >= 30 { result[key] = vaule } } fmt.Println(result) // 输出: map[wangwu:41 ailiu:53 zhangshan:34] }
package main import "fmt" // 接收一个切片,然后遍历得到每个元素出现的个数,返回一个map func WordCount(s ...string) (retmap map[string]int) { retmap = make(map[string]int) for _, item := range s { if _, ok := retmap[item]; ok { retmap[item]++ } else { retmap[item] = 1 } } return } func main() { str := []string{"H", "E", "L", "L", "O", "O", "H", "H"} r := WordCount(str...) // 传一个不定长参数 fmt.Println(r) // 输出: map[E:1 H:3 L:2 O:2] }
package main import "fmt" // 将d2这个map复制到d1中,如果有相同的则覆盖 func main() { d1 := map[int]string{1: "A", 2: "B", 3: "c"} d2 := map[int]string{1: "A100", 200: "B200", 300: "c200"} for key, vaule := range d2 { d1[key] = vaule } fmt.Println(d1) // 输出: map[1:A100 2:B 3:c 200:B200 300:c200] }
六、map排序
map是无序的,如果想为map排序,需要将key或value拷贝到一个切片,在使用sort包对切片进行排序.
下面的例子,key的首字母排序
package main import ( "fmt" "sort" ) func main() { // 定义一个map var fruits = map[string]int{"apple": 21, "banana": 15, "cherry": 95, "durian": 55, "elderberry": 34, "fig": 98, "grape": 47} // 1. 生成一个空的切片,存放所有的key keys := make([]string, len(fruits)) // 2. 标记循环 i := 0 // 3. 遍历fruits这个map,将所有的key放到keys切片中 for key := range fruits { keys[i] = key i++ } // 4. 使用sort包对keys排序,按照首字母排序 sort.Strings(keys) // 5. 遍历keys这个切片,根据key取vaule for _, k := range keys { fmt.Printf("key: %s, vaule: %d\n", k, fruits[k]) } }
浙公网安备 33010602011771号