数据类型之map

章节

  1. map
  2. map声明及初始化
  3. map嵌套
  4. map增删改查
  5. map迭代
  6. 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]
}
过滤map中符合条件的值
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是无序的,如果想为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])
    }
}

 

posted @ 2018-09-25 14:56  opss  阅读(5985)  评论(0)    收藏  举报