Golang數據類型 (map)


前言

Go語言中提供了映射關系容器為map,類似Python中的字典。其內部使用散列表(hash)實現、無序、為引用數據類型。

不同於Python字典之處是map的key可以為數字,在聲明map時就需要指定 map中key和value的數據類型。

為什么很多語言中都有類似map這種鍵值對數據集合呢?因為這種數據類型最大的特點就是查找速度快。

為什么map的查詢速度會特別快呢?

 

map之所以查詢速度快是因為,它可以根據key直接找到數據存儲的位置,而其他數據類型查時從前往后遍歷會比較耗時。就是利用hash存儲。

以上只是hash存儲的基本存儲模型,其他編程語言的鍵值對集合大多基於此基礎進行優化

 

map數據類型有以下3大特點:

鍵不能重復

鍵必須是可hash的(int、bool、float、srting、arry),arry中包含了不可hash元素也不可以!

鍵在map集合中是無序的

 

map聲明

map的key可以是int、bool、float、srting、arry但是arry中不能出嵌套lice元素。

package main

import "fmt"

func main() {
    //1.創建map的方式
    //1.聲明+初始化
    userInfo := map[string]string{"name": "Martin", "age": "18", "e-mail": "13220198866@163.com"}
    fmt.Println(userInfo)
    userList := []map[string]string{map[string]string{"name": "Martin", "age": "18", "e-mail": "martin@163.com"}, map[string]string{"name": "Alex", "age": "70", "e-mail": "Alex@163.com"}}
    userList = append(userList, map[string]string{"name": "zhangdaqian", "age": "188", "e-mail": "zhangdaqian@163.com"})
    fmt.Println(userList)
    //2.make方式
    m1 := make(map[int]int, 10)
    m1[0] = 0
    m1[1] = 1
    fmt.Println(m1)
    //2.聲明map用於整體賦值
    var m2 map[int]int
    //m2["age"]=19 無法設置值 指向nil
    m2=m1
    fmt.Println(m2)

    //3.new用於整體賦值
    m3:=new(map[int]int)
    m3=&m2
    fmt.Println(m3) //返回的是指針
    //4.聲明數組類型的map
    m4:=map[[1]int]int{[1]int{1}:1,[1]int{2}:2}
    m4[[1]int{3}]=3
    m4[[1]int{4}]=4
    fmt.Println(m4)
    /*
    {
    [1]:1,
    [2]:2,
    [3]:3,
    [4]:4

    }
     */
    for k, v := range m4 {
        fmt.Println(k,v)
    }


}

 

map的定義及基本操作

package main

import "fmt"

func main() {
	//定義了1個map變量,key是sring類型、value是int類型
	var m1 map[string]int
	fmt.Println(m1 == nil) //還沒有初始化(沒有在內存中開辟空間)
	//初始化:估算好map的容量,避免程序運行期間在擴容
	m1 = make(map[string]int, 10)
	m1["年齡"] = 18
	fmt.Println(m1)
	fmt.Println(m1["年齡"])
	//獲取不存在的key
	v, ok := m1["姓名"]
	if !ok {
		fmt.Println("沒有該key")
	} else {
		fmt.Println(v)
	}
	//直接獲取不存在的key,返回對應類型的默認值
	fmt.Println(m1["不存在的key"])

	//遍歷map的key和value
	m2 := make(map[string]string, 10)
	m2["姓名"] = "Martin"
	m2["性別"] = "男"
	for k, v := range m2 {
		fmt.Println(k, v)
	}
	//僅遍歷map的keys
	for k := range m2 {
		fmt.Println(k)
	}
	//僅遍歷map的values
	for _, v := range m2 {
		fmt.Println(v)
	}
	//刪除map中的key
	delete(m2,"姓名")
	fmt.Println(m2)
	//刪除map中不存在的key() no-option
	delete(m1,"不存在的key")
	/*
	go doc builtin.delete 查看內置函數的用法
	func delete(m map[Type]Type1, key Type)
    The delete built-in function deletes the element with the specified key
    (m[key]) from the map. If m is nil or there is no such element, delete is a
    no-op.
	*/

}

 

嵌套map  

package main

import "fmt"

func main() {

    m1:=make(map[string]string)
    m1["name"]="Martin"
    m2:=make(map[bool]int)
    m2[true]=1
    m3:=make(map[[2]int][2]string)
    m3[[2]int{1,2}]=[2]string{"a","b"}
    m4:=make(map[string]map[string]string)
    //{"wife":{"name":"Elizabeth","gender":"Female"} }
    m4["wife"]= map[string]string{"name":"Elizabeth","gender":"Female"}
    m4["husband"]= map[string]string{"name":"George","gender":"Male"}
    m5:=map[string][]int{"n1":[]int{1,3,4},"n2":[]int{2,4,6}}
    fmt.Println(m1,m2,m3,m4,m5)
    //[{},{},{}]
    var a1=make([]map[string]string,1,20)
    a1[0]=map[string]string{"name":"eric","gender":"Female","detail":"我是eric我喜歡..."}
    a1=append(a1,map[string]string{"name":"egon","gender":"male","detail":"我是egom我喜歡..."})
    fmt.Println(len(a1))
    fmt.Println(a1)


    //map里面嵌套map
    v6 := make(map[string]map[int]int)
    v6["n1"] = map[int]int{1: 99, 2: 666}
    v6["n2"] = map[int]int{2: 33, 4: 444}
    fmt.Println(v6)

    v7 := make(map[string][2]map[string]string)
    v7["group1"] = [2]map[string]string{map[string]string{"name": "Alex", "age": "18"}, map[string]string{"name": "eric", "age": "34"}}
    v7["group2"] = [2]map[string]string{map[string]string{"name": "Tony", "age": "28"}, map[string]string{"name": "Bob", "age": "23"}}
    fmt.Println(v7)
    /*
        map[group1:[map[age:18 name:Alex] map[age:34 name:eric]] group2:[map[age:28 name:Tony] map[age:23 name:Bob]]]
         {
            group1:[
                {"name":"Alex","age":"18"},
                {"name":"eric","age":"34"}
              ]
            group2:[
               {"name":"Tony","age":"28"},
               {"name":"Bob","age":"23"}
              ]
        }

    */
}

 

 

排序顯示map

無論是Python的字典還是Go中的map,它們都是無序的。那么我們如何對map進行排序呢?就需要1些迂回的方法;

對map的key進行排序做成切片,然后遍歷切片中的key逐一獲取map中的元素。

 

package main

import (
	"fmt"
	"math/rand" //math包中有個rand模塊
	"sort"
	"time"
)

func main() {
	//獲取當前時間的 納秒(隨機數字)
	rand.Seed(time.Now().UnixNano())
	//聲明1個map存放{stud納秒:分數 }
	var scoreMap = make(map[string]int, 200)
	for i := 0; i < 100; i++ {
		key := fmt.Sprintf("stud%2d", i)
		value := rand.Intn(100) //生成0-99的隨機整數(作為分數)
		scoreMap[key] = value
	}

	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(scoreMap[key])
	}

}

  

切片和map組合數據類型

如何在go里面組織這種多維度的數據類型?

1.make創造1個元素為map的切片

 [{"key1":"v1"},{"key2":"v2"}]

創造1個切片[],內部的元素=map[int]string 

2.make創造  值(value)為map的切片

{"ke1":["v1","v2","v3"] }

創造 1個map key為 [string]  值為[]string 

 

package main

import (
	"fmt"
)

//map和slice組合
func main() {
	//1.創造1個切片[],內部的元素=map[int]string 
	var s1 = make([]map[int]string, 10, 10)
	//注意需要對 內部的map也進行初始化
	s1[0] = make(map[int]string, 1)
	s1[0][10] = "北京"
	fmt.Println(s1)
    //2.創造1個map
	var m2 = make(map[string][]string, 10)
	//對map中的切片進行初始化
	m2["北京市"] = []string{"朝陽區", "海淀區", "昌平區"}
	fmt.Println(m2)

}

  

 

 

 

總結

目前主要學到了,Go中的數據類型(string、int、bool、pointer、arry、slice、map)以及怎么定義該數據類型的變量,以便於在使用Go的情況下,存放不同數據模型的數據。

ackage main

import "fmt"

func main() {
	//聲明1個字符串變量
	var name string
	fmt.Println(name)
	//聲明1個數組變量
	var a1 [3]int
	fmt.Println(a1) //聲明完了就有默認值
	//聲明1個切片類型的變量
	var s1 []int
	fmt.Println(s1 == nil)
	//聲明二維數組
	var a3 [3][3]int
	//對二維數組進行初始化
	a3 = [3][3]int{
		[3]int{1, 2, 3},
		[3]int{4, 5, 6},
		[3]int{7, 8, 8},
	}
	fmt.Println(a3)
	//
	a4 := [3]int{1, 2, 3}
	a5 := modifyArry(a4)
	fmt.Println(a4)
	fmt.Println(a5)
	s2 := []string{"北京", "海淀", "五道口"}
	s3 := modifySlice(s2)
	fmt.Println(s2)
	fmt.Println(s3)

	//map數據類型
	var m1 map[string]int
	//注意使用make函數對map進行初始化
	m1 = make(map[string]int, 10)
	//直接使用map
	m2:=make(map[string]int)
	m2["name"]=12
	fmt.Println(m1,m2)

}

//數組是值類型:修改數組時,會復制 1個新的數組讓我們修改
func modifyArry(a1 [3]int) (ret [3]int) {
	a1[0] = 100
	return a1
}

//切片是引用類型:修改切片時,不會復制1個新的切片讓我們修改(修改原來的)
func modifySlice(s2 []string) (ret2 []string) {
	s2[0] = "河北省"
	return s2
}

   

練習

//

// //遍歷數組
// package main

// import (
// 	"fmt"
// )

// func main() {
// 	//根據索引訪問元素
// 	var cities = [...]string{"北京", "上海", "深圳"}
// 	for i := 0; i < len(cities); i++ {
// 		fmt.Printf("%s\n", cities[i])
// 	}

// 	//遍歷數組
// 	for i, v := range cities {
// 		fmt.Println(i, v)
// 	}

// }

// package main

// import (
// 	"fmt"
// )

// func main() {
// 	//arry數值類型辯證
// 	a1 := [...]string{"河北", "河南", "山東"}
// 	a2 := a1
// 	a1[len(a1)-1] = "山西"
// 	fmt.Println(a1) //[河北 河南 山西]
// 	fmt.Println(a2) //[河北 河南 山東]

// }

//練習題目

// package main

// import (
// 	"fmt"
// )

// func main() {
// 	//1.求數組[1, 3, 5, 7, 8]所有元素的和
// 	arr1 := [...]int{1, 3, 5, 7, 8}
// 	var sum int
// 	for _, v := range arr1 {
// 		sum += v
// 	}
// 	fmt.Println(sum)
// 	/*找出數組中和為指定值的兩個元素的下標,比如從數組[1, 3, 5, 7, 8]中找出和為8的兩個元素的下標分別為(0,3)和(1,2)*/
// 	for i := 0; i < len(arr1); i++ {
// 		for j := i + 1; j < len(arr1); j++ {
// 			if arr1[i]+arr1[j] == 8 {
// 				fmt.Printf("%d %d\n", i, j)
// 			}
// 		}
// 	}

// }

// package main

// import "fmt"

// func main() {
// 	//聲明1個字符串變量
// 	var name string
// 	fmt.Println(name)
// 	//聲明1個數組變量
// 	var a1 [3]int
// 	fmt.Println(a1) //聲明完了就有默認值
// 	//聲明1個切片類型的變量
// 	var s1 []int
// 	fmt.Println(s1 == nil)
// 	//聲明二維數組
// 	var a3 [3][3]int
// 	//對二維數組進行初始化
// 	a3 = [3][3]int{
// 		[3]int{1, 2, 3},
// 		[3]int{4, 5, 6},
// 		[3]int{7, 8, 8},
// 	}
// 	fmt.Println(a3)
// 	//
// 	a4 := [3]int{1, 2, 3}
// 	a5 := modifyArry(a4)
// 	fmt.Println(a4)
// 	fmt.Println(a5)
// 	s2 := []string{"河北", "保定", "唐縣"}
// 	s3 := modifySlice(s2)
// 	fmt.Println(s2)
// 	fmt.Println(s3)

// 	//map數據類型
// 	var m1 map[string]int
// 	//注意使用make函數對map進行初始化
// 	m1 = make(map[string]int, 10)
// 	//直接使用map
// 	m2:=make(map[string]int)
// 	m2["name"]=12
// 	fmt.Println(m1,m2)

// }

// //數組是值類型:修改數組時,會復制 1個新的數組讓我們修改
// func modifyArry(a1 [3]int) (ret [3]int) {
// 	a1[0] = 100
// 	return a1
// }

// //切片是引用類型:修改切片時,不會復制1個新的切片讓我們修改(修改原來的)
// func modifySlice(s2 []string) (ret2 []string) {
// 	s2[0] = "河北省"
// 	return s2
// }

package main

import (
	"fmt"
	"strings"
	"unicode"
)

func main() {
	var ChineseCount int
	s1 := "hello你好少年"
	for _, c := range s1 {
		//1.判斷字符是否為漢字(rune類型)
		if unicode.Is(unicode.Han, c) {
			ChineseCount++
		}
	}
	fmt.Printf("漢字的數量為:%d\n", ChineseCount)
	//2.判斷句子中單詞出現的次數(word count)
	word := "how do you do"
	//英文句子中單詞以空格隔開
	WordArry := strings.Split(word, " ")
	wordCountMap := make(map[string]int)
	for _, v := range WordArry {
		_, ok := wordCountMap[v]
		if ok {
			wordCountMap[v]++
		} else {
			wordCountMap[v] = 1
		}

	}
	fmt.Println(wordCountMap)
	//3.判斷句子是否為以下回文句型
	/*
		上海自來水來自海上
		山西運煤車煤運西山
	*/
	LoopSting := "山西運煤車煤運西山"
	//定義1個存放rune字符串(漢字)的切片
	RuneSlice := make([]rune, 0, len(LoopSting))
	for _, c := range LoopSting {
		RuneSlice = append(RuneSlice, c)
	}

	for i := 0; i < len(RuneSlice)/2; i++ {
		if RuneSlice[i] != RuneSlice[len(RuneSlice)-i-1] {
			fmt.Println("不是回文句型")
			return  //在main函數中 return 程序結束
		}
	}
	fmt.Println("是回文句型")

}

  

  

  

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

參考

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM