玩出新花样,给你5个Go语言词频统计扩展练习

简介: 玩出新花样,给你5个Go语言词频统计扩展练习

/ Go 语言词频统计实现 /

词频统计可以分析一段文本中各个词出现的频率,它有许多实用的应用场景,如关键词提取、语言分析等。本文我们将使用 Go 语言实现一个简单的词频统计程序。

主要内容包括:

  1. 问题简述
  2. 初级实现
  3. 分词函数
  4. 数据存储
  5. 统计与输出
  6. 主函数逻辑
  7. 程序测试
  8. 优化思考
  9. 扩展练习

代码示例会包含详细的注释,解释每一段逻辑的具体功能。希望通过详细的实例,可以加深对 Go 语言编程的理解,以及处理文本统计问题的方法。

1

 

1. 问题简述

要求实现一个简单的词频统计程序,功能如下:

  1. 输入一段文本
  2. 对文本进行分词
  3. 统计每个词出现的次数
  4. 按词频输出结果

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 语言编程理解非常有帮助。可以继续优化代码,实现更多扩展功能。


目录
相关文章
|
6天前
|
安全 测试技术 Go
Go语言在高并发场景下的应用
在当今互联网高速发展的时代,高并发已成为众多应用系统面临的核心问题。本文探讨了Go语言在高并发场景下的优势,并通过具体实例展示了其在实际应用中的效果和性能表现。
|
3天前
|
Go
go语言map、实现set
go语言map、实现set
10 0
|
3天前
|
Go
go语言数组与切片
go语言数组与切片
13 0
|
6天前
|
存储 中间件 Go
在go语言服务中封装路由和示例
【6月更文挑战第23天】本文介绍golang后端按协议处理、中间件(一次性与每次请求执行)划分、以及服务架构Controller、Logic/Service、DAO/Repository和Routers划分。代码仓库在GitHub上提供。使用框架简化了交互和处理。后续章节深入探讨服务构建。
104 5
在go语言服务中封装路由和示例
|
2天前
|
Devops Go 云计算
Go语言发展现状:历史、应用、优势与挑战
Go语言发展现状:历史、应用、优势与挑战
|
3天前
|
Go
go语言的hello,world
go语言的hello,world
8 1
|
6天前
|
Unix Go 开发者
探索Go语言并发模型:原理与实践
本文深入探讨了Go语言的并发模型,包括其设计原理、Goroutine和Channel的基本使用,以及如何在实际项目中高效地应用这些概念来提高程序的性能和可维护性。
|
8天前
|
Go
Go 语言是如何实现切片扩容
Go 语言是如何实现切片扩容
|
9天前
|
存储 Go
Go 语言当中 CHANNEL 缓冲
Go 语言当中 CHANNEL 缓冲
|
9天前
|
中间件 Go
go语言后端开发学习(三)——基于validator包实现接口校验
go语言后端开发学习(三)——基于validator包实现接口校验