/ Go 语言词频统计实现 /
词频统计可以分析一段文本中各个词出现的频率,它有许多实用的应用场景,如关键词提取、语言分析等。本文我们将使用 Go 语言实现一个简单的词频统计程序。
主要内容包括:
- 问题简述
- 初级实现
- 分词函数
- 数据存储
- 统计与输出
- 主函数逻辑
- 程序测试
- 优化思考
- 扩展练习
代码示例会包含详细的注释,解释每一段逻辑的具体功能。希望通过详细的实例,可以加深对 Go 语言编程的理解,以及处理文本统计问题的方法。
1
1. 问题简述
要求实现一个简单的词频统计程序,功能如下:
- 输入一段文本
- 对文本进行分词
- 统计每个词出现的次数
- 按词频输出结果
2
2. 初级实现
首先,我们可以使用 map 实现一个简单的单词计数:
// 声明一个map记录词频 frequencies := make(map[string]int) // 输入的文本 input := "hello world hello golang" // 对空格分割文本 words := strings.Split(input, " ") // 统计每个词出现频次 for _, word := range words { frequencies[word]++ } // 输出结果 fmt.Println(frequencies)
这实现了基本的词频统计和输出要求。
3
3. 分词函数
我们可以将文本分词提取封装成一个函数:
// 将文本进行分词 func tokenize(text string) []string { return strings.Split(text, " ") } words := tokenize(input)
这样可以重用分词逻辑。
我们也可以加强对文本的清理处理,比如转换为小写,移除标点等:
func tokenize(text string) []string { // 转小写 text = strings.ToLower(text) // 移除标点 regex, _ := regexp.Compile("[^a-zA-Z]+") text = regex.ReplaceAllString(text, "") // 分词 return strings.Split(text, " ") }
4
4. 数据存储
使用 map 可以灵活统计词频,我们也可以试试数组的方式:
// 定义一个结构体保存词和频次 type Word struct { text string frequency int } var words []Word // 查找某个词,返回索引 func find(word string) int { } // 更新词频 func updateFreq(text string) { index := find(text) if index >= 0 { words[index].frequency++ } }
数组可以按次序存储统计结果。
5
5. 统计与输出
词频统计后,我们按频次排序后输出:
// 按频次对单词排序 sort.Slice(words, func(i, j int) bool { return words[i].frequency > words[j].frequency }) // 按排序后顺序输出结果 for _, w := range words { fmt.Println(w.text, w.frequency) }
sort.Slice 可以按频次对结果排序。
6
6. 主函数逻辑
主函数可以组合上述逻辑完成统计:
func main() { text := "hello world hello golang" words := tokenize(text) // 统计频次 for _, w := range words { updateFreq(w) } // 输出结果 printResults(words) }
主函数负责组合调用其他函数完成统计任务。
7
7. 程序测试
为了测试程序,可以添加一些测试用例:
func TestWordFrequencies(t *testing.T) { text := "hello world hello golang" freqs := getFrequencies(text) if freqs["hello"] != 2 { t.Errorf("hello freq expected 2") } if freqs["golang"] != 1 { t.Errorf("golang freq expected 1") } }
添加一些简单校验可以测试统计结果。
8
8. 优化思考
我们可以考虑以下几点来提升程序:
- 使用 goroutine 并发分词
func tokenizeConcurrent(text string) []string { words := []string{} chunks := splitTextIntoChunks(text) var wg sync.WaitGroup wg.Add(len(chunks)) for _, chunk := range chunks { go func(chunk string) { words = append(words, tokenize(chunk)) wg.Done() }(chunk) } wg.Wait() return words }
测试更多边界用例
func TestWordFrequencies(t *testing.T) { // 边界 testcase testEmpty() testNonAlpha() testLongText() // 正常 testcase testGeneralCase() }
数据存储可以考虑 Trie 树等结构
type Node struct { children map[rune]*Node isWord bool } func buildTrie(words []string) *Node { // ... } func findWord(root *Node, word string) bool { // ... }
使用 channel 通信
func tokenize(text string, c chan []string) { words := // 分词 c <- words } c := make(chan []string) go tokenize(text, c) words := <- c
- 词频保存到数据库
9
9. 扩展练习
一些扩展练习可以考虑:
- 支持统计中文文本词频
- 基于词频给文本打标签
- 生成词云图
- 支持统计文件词频
- 增加停用词过滤
- 构建 inverted index
10
总结
到此我们使用 Go 语言实现了一个简单的词频统计程序,并给出了一些改进思路。充分理解各部分功能,对 Go 语言编程理解非常有帮助。可以继续优化代码,实现更多扩展功能。