map
- map 是 Go 提供的另外一种集合:
- 它可以将 key 映射到 value。
- 可快速通过 key 找到对应的 value
- 它的 key 几乎可以是任何类型
声明 map
- 声明 map,必须指定 key 和 value 的类型:
package main
import "fmt"
func main() {
temperature := map[string]int{
"Earth": 15,
"Mars": -65,
}
temp := temperature["Earth"]
fmt.Printf("On average the Earth is %vº C.\n", temp)
temperature["Earth"] = 16
temperature["Venus"] = 464
fmt.Println(temperature)
moon := temperature["Moon"]
fmt.Println(moon)
if moon, ok := temperature["Moon"]; ok {
fmt.Printf("On average the moon is %vº C.\n", moon)
} else {
fmt.Println("Where is the moon?")
}
_, ok := temperature["Earth"]
fmt.Println(ok)
delete(temperature, "Earth")
}
逗号与 ok 写法
if moon, ok := temperature["Moon"]; ok {
fmt.Printf("On average the moon is %vº C.\n", moon)
} else {
fmt.Println("Where is the moon?")
}
map 不会被复制
- 数组、int、float64 等类型在赋值给新变量或传递至函数/方法的时候会创建相应的副本
- 但 map 不会
package main
import "fmt"
func main() {
planets := map[string]string{
"Earth": "Sector ZZ9",
"Mars": "Sector ZZ9",
}
planetsMarkII := planets
planets["Earth"] = "whoops"
fmt.Println(planets)
fmt.Println(planetsMarkII)
delete(planets, "Earth")
fmt.Println(planetsMarkII)
}
使用 make 函数对 map 进行预分配
- 除非你使用复合字面值来初始化 map,否则必须使用内置的 make 函数来为 map 分配空间。
- 创建 map 时,make 函数可接受一个或两个参数
- 使用 make 函数创建的 map 的初始长度为 0
使用 map 作计数器
package main
import "fmt"
func main() {
temperatures := []float64{
-28.0, 32.0, -31.0, -29.0, -23.0, -29.0, -28.0, -33.0,
}
frequency := make(map[float64]int)
for _, t := range temperatures {
frequency[t]++
}
for t, num := range frequency {
fmt.Printf("%+.2f occurs %d times\n", t, num)
}
使用 map 和 slice 实现数据分组
package main
import (
"fmt"
"math"
)
func main() {
temperatures := []float64{
-28.0, 32.0, -31.0, -29.0, -23.0, -29.0, -28.0, -33.0,
}
groups := make(map[float64][]float64)
for _, t := range temperatures {
g := math.Trunc(t/10) * 10
groups[g] = append(groups[g], t)
}
for g, temperatures := range groups {
fmt.Printf("%v: %v\n", g, temperatures)
}
}
将 map 用作 set
- Set 这种集合与数组类似,但元素不会重复
- Go 语言里没有提供 set 集合
package main
import (
"fmt"
"sort"
)
func main() {
var temperatures = []float64{
-28.0, 32.0, -31.0, -29.0, -23.0, -29.0, -28.0, -33.0,
}
set := make(map[float64]bool)
for _, t := range temperatures {
set[t] = true
}
if set[-28.0] {
fmt.Println("set member")
}
fmt.Println(set)
unique := make([]float64, 0, len(set))
for t := range set {
unique = append(unique, t)
}
sort.Float64s(unique)
fmt.Println(unique)
}
作业题
- 编写一个函数:
- 它可以统计文本字符串中不同单词的出现频率,并返回一个词频 map。
- 该函数需要将文本转换为小写字母并移除包含的标点符号
- strings 包中的 Fields、ToLower、Trim 函数应该对此有所帮助
- 使用该函数统计下文中各单词出现的频率,打印出现不止一次的单词和词频:
As far as eye could reach he saw nothing but the stems of the great plants about him receding in the violet shade, and far overhead the multiple transparency of huge leaves filtering the sunshine to the solemn splendour of twilight in which he walked. Whenever he felt able he ran again; the ground continued soft and springy, covered with the same resilient weed which was the first thing his hands had touched in Malacandra. Once or twice a small red creature scuttled across his path, but otherwise there seemed to be no life stirring in the wood; nothing to fear—except the fact of wandering unprovisioned and alone in a forest of unknown vegetation thousands or millions of miles beyond the reach or knowledge of man.
package main
import (
"fmt"
"strings"
)
func countWords(text string) map[string]int {
words := strings.Fields(strings.ToLower(text))
frequency := make(map[string]int, len(words))
for _, word := range words {
word = strings.Trim(word, `.,"-`)
frequency[word]++
}
return frequency
}
func main() {
text := `As far as eye could reach he saw nothing but the stems of the
great plants about him receding in the violet shade, and far overhead
the multiple transparency of huge leaves filtering the sunshine to the
solemn splendour of twilight in which he walked. Whenever he felt able
he ran again; the ground continued soft and springy, covered with the
same resilient weed which was the first thing his hands had touched in
Malacandra. Once or twice a small red creature scuttled across his
path, but otherwise there seemed to be no life stirring in the wood;
nothing to fear —- except the fact of wandering unprovisioned and alone
in a forest of unknown vegetation thousands or millions of miles
beyond the reach or knowledge of man.`
frequency := countWords(text)
for word, count := range frequency {
if count > 1 {
fmt.Printf("%d %v\n", count, word)
}
}
}