• Golang数据类型之Map


    1、概述

    map(映射)是存储一系列无序的key/value对,通过key来对value进行操作(增、删、改、查)。
    映射的key只能为可使用==运算符的值类型(字符串、数字、布尔、数组),value可以为任意类型

    map的设计也被称为The dictionary problem,它的任务是设计一种数据结构用来维护一个集合的数据,并且可以同时对集合进行增删查改的操作

    Go里的map用于存放key/value对,在其它地方常称为hashdictionary、关联数组,这几种称呼都是对同一种数据结构的不同称呼,它们都用于将key经过hash函数处理,然后映射到value,实现一一对应的关系

    映射是存储一系列无序的key/value对,通过key来对value进行操作(增、删、改、查)

    2、声明

    mapkey至少可以有==、!=运算,值可以为整数、字符串、数组

    value可以是任意类型

    map声明需要指定组成元素keyvalue的类型,在声明后,会被初始化为nil,表示暂不存在的映射0

    var scores map[string]int  // nil映射,光声明map类型但是没有初始化
    fmt.Printf("%T %#v
    ", scores, scores)
    fmt.Println(scores == nil)  // true
    

    关于nil map和空map

    map是不做任何赋值的map

    a := map[int]string
    

    nil map,它将不会做任何初始化,不会指向任何数据结构

    var a map[int]string
    

    如何map没初始化,直接赋值会报空指针

    var a map[int]string
    var b []string
    fmt.Printf("%p, %p
    ", a, b)
    // a[0] = "a"
    // b[0] = "a"
    
    a = map[int]string{0: "a"}
    b = []string{"a"}
    fmt.Printf("%p, %p
    ", a, b)
    

    所以,map类型实际上就是一个指针, 具体为*hmap

    3、初始化

    a) 使用字面量初始化并赋值map[ktype]vtype{k1:v1, k2:v2, …, kn:vn}
    b) 使用字面量初始化空映射map[ktype]vtype{ }
    c) 使用make函数初始化
    make(map[ktype]vtype),通过make函数创建映射,指定容量

    //scores = map[string]int{}
    scores = map[string]int{"a": 8, "b": 9, "c":10}
    fmt.Println(scores)
    //scores = make(map[string]int, 8)
    // 声明map的同时完成初始化
    b := map[int]bool{
        1: true,
        2: false,
    }
    

    4、操作

    4.1 获取元素的数量

    使用len函数获取映射元素的数量

    4.2 访问

    当访问key存在与映射时则返回对应的值,否则返回值类型的零值

    4.3 判断key是否存在

    通过key访问元素时可接收两个值,第一个值为value,第二个值为bool类型表示元
    素是否存在,若存在为true,否则为false

    4.4 修改和增加

    使用key对映射赋值时当key存在则修改key对应的value,若key不存在则增加 keyvalue

    4.5 删除

    使用delete函数删除映射中已经存在的key

    4.6 遍历

    可通过for-range对映射中个元素进行遍历,range返回两个元素分别为映射的key
    value

    上述操作示例:

    // 增删改查
    // key
    fmt.Println(scores["a"])  // 8
    fmt.Println(scores["d"])  // 0  key不存在则为0,但这样不准确
    // v, ok := scores["c"]
    // if ok {
    if v, ok := scores["c"]; ok {
      fmt.Println(v)
      fmt.Println(ok)  // false  判断某个键是否存在
    }
    scores["b"] = 10
    fmt.Println(scores)
    scores["d"] = 20
    fmt.Println(scores)
    // 删除
    delete(scores, "c")  // 按照key删除
    fmt.Println(scores)
    // 获取当前映射元素的数量
    fmt.Println(len(scores))
    // 遍历key、value
    for k, v := range scores {
      fmt.Println(k, v)  // 遍历的顺序和添加的顺序是没有任何关系的
    }
    // 只遍历map中的key
    for k := range scores {
      fmt.Println(k)  // 遍历的顺序和添加的顺序是没有任何关系的
    }
    // 只遍历map中的value
    for _, v := range scores {
      fmt.Println(v)
    }
    
    • 按照某个固定顺序遍历map

    默认情况下,对map遍历后都是无序的,可以通过将map中的key存到切片中,然后对切片元素排序,最终实现对map的有序遍历

    package main
    
    import (
    	"fmt"
    	"math/rand"
    	"sort"
    	"time"
    )
    
    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
    	}
    	// 正常遍历,无序
    	//for k, v := range scoreMap{
    	//	fmt.Println(k, v)
    	//}
    	// 有序遍历,按照key从小到大的顺序遍历scoreMap
    	// 1、取出map中的所有key存入切片keys
    	var keys = make([]string, 0, 200)   // 定义切片
    	for key := range scoreMap {  // 把key添加到切片中
    		keys = append(keys, key)
    	}
    	// 2、对切片进行排序
    	sort.Strings(keys)
    	// 3、按照排序后的key遍历map
    	for _, key := range keys {
    		fmt.Println(key, scoreMap[key])
    	}
    }
    

    4.7 多级map

    多级映射:定义映射的映射

    // 名字 => 映射[字符串]字符串{"1", "2", "3"}
    var users map[string]map[string]string
    users = map[string]map[string]string{"北京": {"1": "朝阳", "2": "东城", "3": "西城"}}
    fmt.Printf("%T, %#v
    ", users, users)
    _, ok := users["上海"]
    fmt.Println(ok)  // false
    users["上海"] = map[string]string{"1": "浦东", "2": "徐汇", "3": "静安"}
    fmt.Println(users)  // map[上海:map[1:浦东 2:徐汇 3:静安] 北京:map[1:朝阳 2:东城 3:西城]]
    users["上海"]["3"] = "虹桥"
    fmt.Println(users)  // map[上海:map[1:浦东 2:徐汇 3:虹桥] 北京:map[1:朝阳 2:东城 3:西城]]
    delete(users["北京"], "1")
    fmt.Println(users)  // map[上海:map[1:浦东 2:徐汇 3:虹桥] 北京:map[2:东城 3:西城]]
    
  • 相关阅读:
    HDU 1224 无环有向最长路
    HDU 1220 简单数学题
    HDU 1203 背包问题
    HDU 1176 DP
    HDU 1159 LCS最长公共子序列
    HDU 1160 排序或者通过最短路两种方法解决
    hdu 2349 最小生成树
    次小生成树的学习
    最小生成树prime算法模板
    poj 1679 判断最小生成树是否唯一
  • 原文地址:https://www.cnblogs.com/ssgeek/p/15017932.html
Copyright © 2020-2023  润新知