一、集合(Map)

1.1 什么是Map

map是Go中的内置类型,它将一个值与一个键关联起来。可以使用相应的键检索值。

Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。
Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的,也是引用类型。

使用map过程中需要注意的几点:

  • map是无序的,每次打印出来的map都会不一样,它不能通过 index 获取,而必须通过key获取。类似于 PHP 的索引数组
  • map的长度是不固定的,也就是和slice一样,也是一种引用类型
  • 内置的 len 函数同样适用于 map,返回 map 拥有的 key 的数量
  • map 的 key 可以是所有可比较的类型,如布尔型、整数型、浮点型、复杂型、字符串型……也可以键。

1.2 Map的使用

1.2.1 使用make()创建 map

可以使用内建函数 make 也可以使用 map 关键字来定义 Map:

/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type

/* 使用 make 函数 */
map_variable = make(map[key_data_type]value_data_type)
rating := map[string]float32 {"C":5, "Go":4.5, "Python":4.5, "C++":2 }

如果不初始化 map,那么就会创建一个 nil map。nil map 不能用来存放键值对

package main

import "fmt"

func main() {
   var countryCapitalMap map[string]string
   /* 创建集合 */
   countryCapitalMap = make(map[string]string)

   /* map 插入 key-value 对,各个国家对应的首都 */
   countryCapitalMap["France"] = "Paris"
   countryCapitalMap["Italy"] = "Rome"
   countryCapitalMap["Japan"] = "Tokyo"
   countryCapitalMap["India"] = "New Delhi"

   /* 使用 key 输出 map 值 */
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }

   /* 查看元素在集合中是否存在 */
   captial, ok := countryCapitalMap["United States"]
   /* 如果 ok 是 true, 则存在,否则不存在 */
   if(ok){
      fmt.Println("Capital of United States is", captial)  
   }else {
      fmt.Println("Capital of United States is not present") 
   }
}

运行结果:

Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of India is New Delhi
Capital of United States is not present

1.2.2 delete() 函数

delete(map, key) 函数用于删除集合的元素, 参数为 map 和其对应的 key。删除函数不返回任何值。

package main

import "fmt"

func main() {   
   /* 创建 map */
   countryCapitalMap := map[string] string {"France":"Paris","Italy":"Rome","Japan":"Tokyo","India":"New Delhi"}

   fmt.Println("原始 map")   

   /* 打印 map */
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }

   /* 删除元素 */
   delete(countryCapitalMap,"France");
   fmt.Println("Entry for France is deleted")  

   fmt.Println("删除元素后 map")   

   /* 打印 map */
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }
}

运行结果:

原始 map
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of India is New Delhi
Entry for France is deleted
删除元素后 map
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of India is New Delhi

1.2.3 ok-idiom

我们可以通过key获取map中对应的value值。语法为:

map[key] 

但是当key如果不存在的时候,我们会得到该value值类型的默认值,比如string类型得到空字符串,int类型得到0。但是程序不会报错。

所以我们可以使用ok-idiom获取值,可知道key/value是否存在

value, ok := map[key] 

示例代码:

package main

import (
    "fmt"
)

func main() {
    m := make(map[string]int)
    m["a"] = 1
    x, ok := m["b"]
    fmt.Println(x, ok)
    x, ok = m["a"]
    fmt.Println(x, ok)
}

运行结果:

0 false
1 true

1.2.4 map的长度

使用len函数可以确定map的长度。

len(map)  // 可以得到map的长度

1.2.5 map是引用类型的

与切片相似,映射是引用类型。当将映射分配给一个新变量时,它们都指向相同的内部数据结构。因此,一个的变化会反映另一个。

示例代码:

package main

import (  
    "fmt"
)

func main() {  
    personSalary := map[string]int{
        "steve": 12000,
        "jamie": 15000,
    }
    personSalary["mike"] = 9000
    fmt.Println("Original person salary", personSalary)
    newPersonSalary := personSalary
    newPersonSalary["mike"] = 18000
    fmt.Println("Person salary changed", personSalary)

}

运行结果:

Original person salary map[steve:12000 jamie:15000 mike:9000]  
Person salary changed map[steve:12000 jamie:15000 mike:18000] 

map不能使用操作符进行比较。只能用来检查map是否为空。否则会报错:invalid operation: map1 map2 (map can only be comparedto nil)

2、练习

package main

import (
    "fmt"
)

func main() {
    /*
        map: 映射,是一种专门用于存储键值对的集合,属于引用类型

        存储特点:
            A:存储的是无序的键值对
            B: 键名不能重复,并且和value值一一对应的
                map中的key不能重复,如果重复,那么新的value会覆盖原来的,程序不会报错
                (这种玩法和PHP的关联数组基本是一样的)
            语法结构:
                1。创建map
                    var map1 map[key类型]value类型
                    nil map,无法直接使用

                    var map2 = make(map[key类型])value类型

                    var map3 = map[key类型]value类型{key:value,key1:value1,key2:value2……}

                2。添加修改
                    map[key]=value
                    如果 key 不存在,就是添加数据,如果 key 存在,就是修改数据

                3、获取
                    map[key] ---> value

                    value,ok := map[key]
                        根据 key 获取对应的 value, 如果 key 存在,value 就是对应的数据, ok 为 true, 否则,value 就是值类型的默认值,ok 为 false

                4、删除数据
                    delete(map[key])
                        如果 key 存在,就可以直接删除,否则,删除失败

                5、长度
                    len(map)

                6、每种数据类型对应的默认值
                    int:0
                    float: 0或者0.0
                    string: ""
                    array: [0000000]

                    slice: nil
                    map: nil
    */
    // 1。创建 map
    var map1 map[int]string         // 没有初始化,直接创建
    var map2 = make(map[int]string) // 创建,没初始货
    // 创建并初始化
    var map3 = map[string]string{"name": "雨林之后", "email": "yulinzhihou@163.com", "age": "18 years old"}

    fmt.Println(map1, map2, map3)

    // 判断一下
    fmt.Println(map1 == nil) // true
    fmt.Println(map2 == nil) // false : make 声明了 key 和 value 的类型,所以是对应的类型的默认值
    fmt.Println(map3 == nil) // false

    // 2、nil map 种类
    if map1 == nil {
        map1 = make(map[int]string)
        fmt.Println(map1 == nil)
    }

    // 3、存储键值对到 map 中
    map3["name"] = "张三"
    map3["email"] = "yulinzhihou@164.com"
    map3["com"] = "yulinzhihou.com"

    fmt.Println(map1, map2, map3)

    // 4、获取数据
    fmt.Println(map3["com"])
    v1, ok := map3["com"]
    if ok {
        fmt.Println("获取 com 的值为:" + v1)
    } else {
        fmt.Println("获取 com 失败")
    }

    // 5、删除数据
    delete(map3, "com")
    v2, ok1 := map3["com"]
    if ok1 {
        fmt.Println("获取 com 的值为:" + v2)
    } else {
        fmt.Println("获取 com 失败")
    }

    // 6、长度
    fmt.Println(len(map3))
}

package main

import (
    "fmt"
    "sort"
)

func main() {
    /*
        map 的遍历:
            使用: for range
            数组,切片: index.value (索引数组)
            map: key.value  (关联数组)
    */

    map1 := map[int]string{}
    map1[1] = "段誉"
    map1[2] = "阿紫"
    map1[4] = "萧峰"
    map1[3] = "虚竹"
    map1[5] = "慕容复"
    map1[6] = "段正明"
    map1[7] = "阿朱"
    map1[8] = "游坦之"
    map1[9] = "丁春秋"

    // 1、遍历
    for key, value := range map1 {
        fmt.Printf("key = %d , value = %s \n", key, value)
    }

    fmt.Println("****************我*******是*******分*******隔**********线**************")

    for i := 1; i <= len(map1); i++ {
        fmt.Printf("i = %d , value = %s \n", i, map1[i])
    }

    /*
        1.遍历所有的 key,---- 切片,数组
        2、进行排序
        3、遍历key, map[key]
    */

    keys := make([]int, 0, len(map1))
    fmt.Println(keys)

    for k, _ := range map1 {
        keys = append(keys, k)
    }
    fmt.Println(keys)

    // 冒泡排序,直接使用 sort 包下的排序
    sort.Ints(keys)
    fmt.Println(keys)

    // slice
    slice01 := []string{"abc", "def", "ghi", "张三", "mno", "pqr", "tuv", "wxyz"}
    fmt.Println(slice01)
    sort.Strings(slice01)
    fmt.Println(slice01)
}

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。