Golang基础-数据结构-map

这篇博客介绍了 Golang 中的数据结构 Map,包括如何定义、初始化、访问元素、删除元素、遍历以及特殊情况下的遍历顺序。还讨论了如何判断 Map 中元素是否存在,以及 Map 类型元素为切片的情况。最后提供了两个案例,一个是判断两个 Map 是否包含相同键值,另一个是寻找最长不含重复字符的子串问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义

map:一个无序的key-value对的集合,其中所有的key的值不同,通过给定的key对其进行检索、更新或删除可以在 O(1) 的时间复杂度内完成。

map[KeyType]ValueType

其中 KeyType表示键的类型 ValueType表示键对应值的类型

基本使用

初始化

make(map[KeyType]ValueType, [cap])

其中 cap表示map的容量,该参数虽然不是必须的,但是我们应该在初始化map的时候就为其指定一个合适的容量。

ages := make(map[string]int)

map字面值的语法创建map,同时指定一些初始值

ages := map[string]int{
    "alice":   31,
    "tom": 34,
}

相当于

ages := make(map[string]int)
ages["alice"] = 31
ages["tom"] = 34

元素的访问 key中的value

ages["jack"] = 32
fmt.Println(ages["jack"]) // "32"

删除元素

格式:delete(map, key)

delete(ages, "alice") // remove element ages["alice"]

遍历

可以用for-range进行遍历

for name, age := range ages {
    fmt.Printf("%s\t%d\n", name, age)
}

注意:遍历的顺序是随机的

这是故意的,每次都使用随机的遍历顺序可以强制要求程序不会依赖具体的哈希函数实现。----《Go语言圣经》

按指定顺序遍历

如果要按顺序遍历key/value对,我们必须显式地对key进行排序,可以使用sort包的Strings函数对字符串slice进行排序。

import "sort"

var names []string
for name := range ages {
    names = append(names, name)
}
sort.Strings(names)
for _, name := range names {
    fmt.Printf("%s\t%d\n", name, ages[name])
}

其他例子:

func main() {
	rand.Seed(time.Now().UnixNano()) //初始化随机数种子

	var scoreMap = make(map[string]int, 200)

	for i := 0; i < 100; i++ {
		key := fmt.Sprintf("stu%02d", i) //生成stu开头的字符串
		value := rand.Intn(100)          //生成0~99的随机整数
		scoreMap[key] = value
	}
	//取出map中的所有key存入切片keys
	var keys = make([]string, 0, 200)
	for key := range scoreMap {
		keys = append(keys, key)
	}
	//对切片进行排序
	sort.Strings(keys)
	//按照排序后的key遍历map
	for _, key := range keys {
		fmt.Println(key, scoreMap[key])
	}
}

判断某个值是否存在

if age, ok := ages["bob"]{
	fmt.Println(age)
}else{
	fmt.Println("查无此人")
}

元素为map类型的切片

func main() {
		var mapSlice = make([]map[string]string, 3)
	for index, value := range mapSlice {
		fmt.Printf("index:%d value:%v\n", index, value)
		// index:0 value:map[]
		// index:1 value:map[]
		// index:2 value:map[]
	}
	fmt.Println("after init")
	// 对切片中的map元素进行初始化
	mapSlice[0] = make(map[string]string, 10)
	mapSlice[0]["name"] = "小羊爱吃肉"
	mapSlice[0]["password"] = "123456"
	mapSlice[0]["address"] = "湖北"
	for index, value := range mapSlice {
		fmt.Printf("index:%d value:%v\n", index, value)
		// index:0 value:map[address:湖北 name:小羊爱吃肉 password:123456]
		// index:1 value:map[]
		// index:2 value:map[]
	}
}

值为切片类型的map

func main() {
		var sliceMap = make(map[string][]string, 3)
	fmt.Println(sliceMap)
	// map[]
	fmt.Println("after init")
	key := "中国"
	value, ok := sliceMap[key]
	if !ok {
		value = make([]string, 0, 2)
	}
	value = append(value, "北京", "上海")
	sliceMap[key] = value
	fmt.Println(sliceMap)
	// map[中国:[北京 上海]]
}

案例

判断两个map是否包含相同的key和value

和slice一样,map之间也不能进行相等比较;唯一的例外是和nil进行比较。要判断两个map是否包含相同的key和value,我们必须通过一个循环实现:

func equal(x, y map[string]int) bool {
    if len(x) != len(y) {
        return false
    }
    for k, xv := range x {
        if yv, ok := y[k]; !ok || yv != xv {
            return false
        }
    }
    return true
}
func main(){
	if equal(map[string]int{"A": 0}, map[string]int{"B": 42}) {
		println("true")
	} else {
		println("false")
	}
}

以上案例来自于《Go语言圣经》

寻找最长不含重复字符的子串

// abcabcbb找出abc bbbbb找出b pwwkew找出wke
package main

import "fmt"

func length0fnonrepeatingsubstr(s string) int {
	last0ccurred := make(map[byte]int)
	start := 0
	maxlength := 0
	for i, ch := range []byte(s) {

		if lastI, ok := last0ccurred[ch]; ok && lastI >= start {
			start = lastI + 1
		}
		if i-start+1 > maxlength {
			maxlength = i - start + 1
		}
		last0ccurred[ch] = i
	}
	return maxlength
}
func main() {
	fmt.Println(
		length0fnonrepeatingsubstr("abcabcbb"))
	fmt.Println(
		length0fnonrepeatingsubstr("bbbbb"))
	fmt.Println(
		length0fnonrepeatingsubstr("pwwkew"))
	fmt.Println(
		length0fnonrepeatingsubstr(""))
	fmt.Println(
		length0fnonrepeatingsubstr("abcdef"))
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值