1. 写一个程序,统计一个字符串中每个单词出现的次数。比如:”how do you do”中how=1 do=2 you=1。
代码如下:
package main
import (
"fmt"
"strings"
)
func main() {
s := "how do you do"
fmt.Println(WordCount(s))
}
func WordCount(s string) map[string]int {
//return map[string]int{"x": 1}
m := make(map[string]int) // map对象k是单词、v是单词出现个数
c := strings.Fields(s) // []byte
for _, v := range c {
m[v] += 1 //map中没有k,v就+1 有的话就增加一个v
}
return m
}
运行截图:
这里用到了内置的string包的Field方法来分隔单词,具体来讲,Field功能如下:
1. Fields 以连续的空白字符为分隔符,将 s 切分成多个子串,结果中不包含空白字符本身;
2. 空白字符有:\t, \n, \v, \f, \r, ’ ', U+0085 (NEL), U+00A0 (NBSP);
3. 如果 s 中只包含空白字符,则返回一个空列表。
由此看来,这种计词方法只能对一些简单的字符串起效,而如果遇上了"how do you do?",你就会发现“do?”也被计词一次。
2. 观察下面代码,写出最终的打印结果。
func main() {
type Map map[string][]int
m := make(Map)
s := []int{1, 2}
s = append(s, 3)
fmt.Printf("%+v\n", s)
m["q1mi"] = s
s = append(s[:1], s[2:]...)
fmt.Printf("%+v\n", s)
fmt.Printf("%+v\n", m["q1mi"])
}
先上运行截图:
map[“q1mi”]的value竟然是[1 3 3],而且竟然是跟s的地址一样的情况下与s切片的内容不一样!
进行断点调试:
图一:
图二
看图分析,图一与我们的猜想是相符的——无论是两者的长度、容量还是其底层的数组都是完全一样的。到了图二,仔细看二者的不同之处,我在图中用不同颜色的框框标注的部分。红框框中的两个键值对的key由图一的红色变成了蓝色,是从图一到图二发生变化的部分。这样一看大家就能明白怎么回事儿了,原博客中讲到:
因此,s = append(s[:1], s[2:]...)
其实就是删除切片中index为1的元素:2。由下图:
再结合断点调试的图二可以得知,删除切片中的元素其实是把删除元素后面的元素向前一位复制一份,切片的长度len再减一,map[“q1mi”]与slice s指针指向的位置相同,但s长度的长度少1,所以会比map[“q1mi”]少一个元素3。
我移动s的右指针后证实了这个猜想。见下图:
map这节的第二题花费了我不少时间,询问了很多大佬也查了不少资料。最终的结果算是给了自己一个交待。作为初学者,寻根问底对后面知识的学习会有很大帮助,同时作为初学者的我也可能会出现纰漏,望大家能指出。
参考文章:go语言关于切片类型内存地址的理解
题目出处:[李文周Go基础之map基础]