Golang中map的操作

map

Golang中map官方定义为映射。
基本介绍
mapkey-value数据结构,一种键值对形式的集合,又称为字段或者关联数组。类似其它编程语言的集合,在编程中经常使用到。

基本语法
var m变量名 map[关键字类型type] 指定值类型type

key的类型: golang中mapkey具有多种类型,比如bool、数值、string、指针、管道channel,还可以是包含前面几个类型的接口,结构体、数组。通常为int、string类型注意:slice,map,function不可以作为key,因为这几个类型不能使用==进行判断。

value的类型:key的类型基本一样,多了map类型,通常为: 数字(整数、浮点数)、string、map、struct

map声明举例:

var a map[string]string //key类型string value类型 string
var a map[string]int
var a map[int]string
var a map[int]map[string]int// key类型int value类型map[string]int 
//map可以包含多重map

注意:
1.map声明是不会分配内存的,初始化需要make,分配内存后才能赋值和使用。(slice也是如此)
2.map的键值key是不可以重复的,值value是可以重复。
3.key所对应的value值是可以修改的
4.map中的key-value无序的

func main() {
	//map的声明和注意事项
	var a map[string]string
	//在使用map必须使用make,给map分配数据空间
	fmt.Println(a) // nil map[]
	a = make(map[string]string, 10)

	//map 赋值操作
	a["no.1"] = "宋江"
	a["no.2"] = "吴用"
	fmt.Println(a) //map[no.1:宋江 no.2:吴用]

	//关键字不可重复
	a["no.1"] = "武松"
	fmt.Println(a) //map[no.1:武松 no.2:吴用]

	//value 可以相同
	a["no.3"] = "吴用"
	fmt.Println(a) //map[no.1:武松 no.2:吴用 no.3:吴用]

	a["no.4"] = "鲁智深"
	a["no.5"] = "晁盖"
	a["no.6"] = "孙二娘"

	//Golang的map的key-value 是遍历是无序的
	for i, v := range a {
		fmt.Printf("%v元素是%v\n", i, v)

	}
	/*
		no.2元素是吴用
		no.3元素是吴用
		no.1元素是武松
		no.4元素是鲁智深
		no.5元素是晁盖
		no.6元素是孙二娘*/
}

map的使用方式:

	var a map[string]string
	//在使用map必须使用make,给map分配数据空间
	a = make(map[string]string, 10)
	//map 赋值操作
	a["no.1"] = "宋江"
	a["no.2"] = "吴用"
	fmt.Println(a) //map[no.1:宋江 no.2:吴用]

	//第二种方式 类型推导
	cite := make(map[string]string, 10)
	cite["no.1"] = "北京"
	cite["no.2"] = "南京"
	cite["no.2"] = "武汉"
	fmt.Println(cite) //map[no.1:北京 no.2:武汉]

	//第三种形式  类型推导 +直接使用
	hero := map[string]string{
		"hero1": "武松",
		"hero2": "卢俊义", // 最后一行也必须有“,”
	}
	fmt.Println(hero) //map[hero1:武松 hero2:卢俊义]

使用案例
要求:
演示一个 key-value 的valeu是map类型的案例
要求:存放三个学生的信息,每个学生有学号 、name 和sex等信息

studentMap := make(map[string]map[string]string)

	//value是map类型的,还需进行make,才能使其分配空间,进行赋值操作
	studentMap["01234"] = make(map[string]string, 3)
	studentMap["01234"]["name"] = "tom"
	studentMap["01234"]["sex"] = "male"
	studentMap["01234"]["address"] = "武汉天地~"

	studentMap["01235"] = make(map[string]string, 3)
	studentMap["01235"]["name"] = "marry"
	studentMap["01235"]["sex"] = "female"
	studentMap["01235"]["address"] = "武汉天地~"

	studentMap["01236"] = make(map[string]string, 3)
	studentMap["01236"]["name"] = "Jay"
	studentMap["01236"]["sex"] = "male"
	studentMap["01236"]["address"] = "武汉天地~"

	fmt.Println(studentMap)
	fmt.Println(studentMap["01234"]) //map[address:武汉天地~ name:tom sex:male]
	fmt.Println(studentMap["01234"]["name"]) //tom

map的增删改查操作
1.map的增加和更新:
map["key"] = vlaue,如果key不存在,就是增加操作;如果key存在,就是修改操作。

	cite := make(map[string]string, 10)
	cite["no.1"] = "北京" //如果没有no.1这个key,就是增加
	cite["no.2"] = "南京" //如果没有no.2这个key,就是增加
	fmt.Println(cite)   //map[no.1:北京 no.2:南京]
	cite["no.2"] = "武汉" //如果有no.2这个key,就是修改
	fmt.Println(cite)   //map[no.1:北京 no.2:武汉]
}

2.map的删除:
使用内嵌函数deletedelete(map,"key"),如果key存在,就删除该key-value关联数组;如果key不存在,则不进行删除操作,但也不会报错。

Golang中map的操作_第1张图片

	//演示删除
	delete(cite, "no.1")
	fmt.Println(cite) // map[no.2:武汉]
	//当delete指定的key不存在时,不进行删除操作,但也不会报错
	delete(cite, "no.4")
	fmt.Println(cite) // map[no.2:武汉]

map删除细节说明:
1)想要删除map中的所有key,在Golang中没有一个专门的方法实现一次性删除,可以遍历一下key,逐个删除
2)使用map = make(...),make一个新的,让原来的成为垃圾,被gc回收。

// 一次性删除所有的key
	// 1.遍历所有的key,逐一删除
	heroname := map[string]string{
		"hero1": "武松",
		"hero2": "九纹龙",
		"hero3": "黑旋风",
	}
	fmt.Println(heroname)     //map[hero1:武松 hero2:九纹龙 hero3:黑旋风]
	for k,_:= range heroname { //map的遍历支持遍历key,也可写成 k:= range heroname
		delete(heroname, k)
	} 
	fmt.Println(heroname) //map[]

	//2.直接make一个新空间
	heroname1 := map[string]string{
		"hero1": "武松",
		"hero2": "九纹龙",
	}
	fmt.Println(heroname1) //map[hero1:武松 hero2:九纹龙]
	heroname1 = make(map[string]string)
	fmt.Println(heroname1) //map[]

  1. map的查找
    map映射中查找是否含有某个key键值,使用val,judge := m[key1],其中变量val类型与m映射的值类型相同,judge类型为bool类型。
    若映射m中含有key1键值,则val = m[key1]即将m映射中key1键对应的值赋给变量val,并且此时变量judge为true;若映射m中不含有key1键值,则此时变量judge为false

案例演示:

	movieName := make(map[string]string)
	movieName["American"] = "Revenger"
	movieName["Chinese"] = "满城尽带黄金甲"
	//map的查找
	// 如果movieName映射中存在key"Chinese",则把key"Chinese"对应的值赋给val,给judge赋值为true
	//否则judge 为 false
	val, judeg := movieName["Chinese"]

	if judeg {
		fmt.Printf("movieName映射中含义key:Chinese,对应的值为%v", val)
	} else {
		fmt.Println("movieName映射中不含义key:Chinese")

	}

}

Output:
movieName映射中含义key:Chinese,对应的值为满城尽带黄金甲

map遍历
map的遍历使用for-range结构遍历;当mapvaluemap类型时,使用多重for-range结构遍历。

案例演示:

ctiesName := make(map[string]map[string]string)
	ctiesName["武汉"] = map[string]string{
		"省份": "湖北",
		"车牌": "鄂A",
		"景点": "黄鹤.楼....",
	}

	ctiesName["北京"] = make(map[string]string)
	ctiesName["北京"]["省份"] = "直辖市"
	ctiesName["北京"]["车牌"] = "京牌"
	ctiesName["北京"]["景点"] = "天安门..."

	//map 的遍历
	// 使用for—range结构,遍历所得是键key 和 值value。(map是无序的故不可遍历得下标)
	for k1, v1 := range ctiesName {
		fmt.Println("k1=", k1)
		for k2, v2 := range v1 {
			fmt.Printf("\t k2=%v,对应的值v2=%v\n", k2, v2)
		}
	}

Output:
k1= 武汉
k2=景点,对应的值v2=黄鹤楼…
k2=省份,对应的值v2=湖北
k2=车牌,对应的值v2=鄂A
k1= 北京
k2=省份,对应的值v2=直辖市
k2=车牌,对应的值v2=京牌
k2=景点,对应的值v2=天安门…


统计map的长度
同样使用内建函数len()


map切片

基本介绍:当切片的类型是map时,则称为slice of map,map切片s:=make([]map[type1]type),这样则使得map的个数可以动态变化。

案例演示:

要求使用一个map来记录monster的信息(name和age),即monster的value是一个map类型,并且怪兽的个数可动态增加(map切片)。

//map切片的使用
	//1.声明一个map切片
	mapSlice := make([]map[string]string, 2) //准备放入两个妖怪
	//增加妖怪的信息
	if mapSlice[0] == nil {

		mapSlice[0] = make(map[string]string)
		mapSlice[0]["name"] = "牛魔王"
		mapSlice[0]["age"] = "1000岁"
	}
	if mapSlice[1] == nil {
		mapSlice[1] = make(map[string]string)
		mapSlice[1]["name"] = "猪八戒"
		mapSlice[1]["age"] = "990岁"
	}
	fmt.Println(mapSlice) //[map[age:1000岁 name:牛魔王] map[age:990岁 name:猪八戒]]

	//切片定义长度后,切片包含元素不能超过其长度(未定义容易情况下)
	//下面操作会报错,越界。
	// if mapSlice[2] == nil {
	// 	mapSlice[2] = make(map[string]string)
	// 	mapSlice[2]["name"] = "蜘蛛精"
	// 	mapSlice[2]["age"] = "999岁"
	// }

	//使用切片的动态append函数,可动态增加monster的
	//1.新建一个monster信息
	monster := map[string]string{
		"name": "金角大王",
		"age":  "1000岁",
	}
	mapSlice = append(mapSlice, monster)
	fmt.Println(mapSlice)
	//[map[age:1000岁 name:牛魔王] map[age:990岁 name:猪八戒] map[age:1000岁 name:金角大王]]

	// 2.直接增加map内容
	mapSlice = append(mapSlice, map[string]string{"name": "孙悟空", "age": "1500岁"})
	fmt.Println(mapSlice)
	// [map[age:1000岁 name:牛魔王] map[age:990岁 name:猪八戒] map[age:1000岁 name:金角大王] map[age:1500岁 name:孙悟空]]

	fmt.Println(mapSlice[2], mapSlice[3]) //map[age:1000岁 name:金角大王] map[age:1500岁 name:孙悟空]

Noting:
1)map的使用时,在声明\定义时,未定义长度\定义了长度情况下都是可以无限创建key-value对的,即map映射会具有动态增加自身长度的功能。

	m := make(map[int]string, 2)
	m[1] = "abc"
	m[2] = "abcd"
	fmt.Println(m)      //map[1:abc 2:abcd]
	fmt.Println(len(m)) //2
	//再增加一个关联数组则也不会报错
	m[3] = "bcd"
	fmt.Println(m)      //map[1:abc 2:abcd 3:bcd]
	fmt.Println(len(m)) //3

2)不可对已存在的map映射直接进行切片处理,因为map本质上键值对集合是无序的。
3)若想将已有的map内容赋给某切片,可以使用map切片+append方法

	monster := map[string]string{
			"name": "金角大王",
			"age":  "1000岁",
		}
	//2)
	//noting
	//不可对已存在的`map`映射直接进行切片处理,因为`map`本质上键值对集合是无序的。
	//下面操作报错,不可对map进行切片	
	// mapSlice02 := monster[:]
	//3)
	mapSlice1 := make([]map[string]string, 0)
	mapSlice1 = append(mapSlice1, monster)
	fmt.Println(mapSlice1)//[map[age:1000岁 name:金角大王]]

map排序
基本介绍:
1)golang中没有一个专门的方法针对map的key进行排序
2)golang中的map默认是无序的,注意:也不是按照添加的顺序存放,每次遍历得到的输出结果都可能不一样的
3)golang中map的排序,先是将key进行切片化处理,使用sort函数包进行排序,然后根据key值遍历输出

	m := make(map[int]string, 10)

	m[0] = "1"
	m[1] = "2"
	m[2] = "3"
	m[9] = "6"

	fmt.Println(m)

	for k, v := range m {
		fmt.Printf("key=%v,value=%v\n", k, v)
	} //输出结果是无序的

	// 要求按照map的key的顺序进行排序输出
	// 1.先将map的key放入到切片中
	// 2.对切片进行排序
	// 3.遍历切片,然后按照key来输出map的值

	var keys []int
	for k := range m {
		keys = append(keys, k)
	}

	//排序 升序
	sort.Ints(keys)
	fmt.Println(keys) //[0 1 2 9]

	for _, v := range keys {
		fmt.Printf("m[%v]=%v\n", v, m[v])
	}
	/* m[0] = 1
	   m[1] = 2
	   m[2] = 3
	   m[9] = 6 */
	fmt.Println()

	//排序 降序
	sort.Sort(sort.Reverse(sort.IntSlice(keys)))
	for _, v := range keys {
		fmt.Printf("m[%v]=%v\n", v, m[v])
	}
	/*m[9] = 6
	  m[2] = 3
	  m[1] = 2
	  m[0] = 1 */

map使用细节
1)map是引用类型,遵守引用类型地址传递机制(地址传递)。在一个函数接收map,修改后,会直接修改原来的map。

func modify(m map[int]int) {
	m[10] = 100
}
func main() {
	m := make(map[int]int)
	m[1] = 10
	m[2] = 130
	m[10] = 18
	m[20] = 119

	modify(m)
	fmt.Println(m)
	//map[1:10 2:130 10:100 20:119]  说明map是引用类型

2)map的容量达到后,再想增加map的元素,会自动扩容,并不会发生panic,即map能动态的增长键值对。
3)map的value也经常是struct类型,更适合管理复杂的数据。

type stuInfo struct {
	Name    string
	Age     int
	Sex     string
	Address string
}
func main() {
studenMap := make(map[string]stuInfo)

	//定义结构体 再赋值
	stu0 := stuInfo{Name: "Alex", Age: 18, Sex: "男", Address: "武汉"}
	stu1 := stuInfo{"Alice", 18, "女", "南京"}
	studenMap["1020"] = stu0
	studenMap["1021"] = stu1
	//直接赋值
	studenMap["1022"] = stuInfo{"Ming", 18, "男", "北京"}
	fmt.Println(studenMap)
	// map[1020:{Alex 18 男 武汉} 1021:{Alice 18 女 南京} 1022:{Ming 18 男 北京}]

	// 遍历形式
	for k, v := range studenMap {
		fmt.Printf("学生的学号是%v\n", k)
		fmt.Printf("\t学生的名字是%v\n", v.Name)
		fmt.Printf("\t学生的年龄是%v\n", v.Age)
		fmt.Printf("\t学生的性别是%v\n", v.Sex)
		fmt.Printf("\t学生的地址是%v\n", v.Address)
		fmt.Println()
	}
	/*	学生的学号是1020
	        学生的名字是Alex
	        学生的年龄是18
	        学生的性别是男
	        学生的地址是武汉
	        ....
}

你可能感兴趣的:(golang,leetcode,开发语言)