玩出新花样,给你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天前
|
存储 JSON 监控
Viper,一个Go语言配置管理神器!
Viper 是一个功能强大的 Go 语言配置管理库,支持从多种来源读取配置,包括文件、环境变量、远程配置中心等。本文详细介绍了 Viper 的核心特性和使用方法,包括从本地 YAML 文件和 Consul 远程配置中心读取配置的示例。Viper 的多来源配置、动态配置和轻松集成特性使其成为管理复杂应用配置的理想选择。
23 2
|
4天前
|
Go 索引
go语言中的循环语句
【11月更文挑战第4天】
13 2
|
4天前
|
Go C++
go语言中的条件语句
【11月更文挑战第4天】
15 2
|
8天前
|
程序员 Go
go语言中的控制结构
【11月更文挑战第3天】
84 58
|
7天前
|
监控 Go API
Go语言在微服务架构中的应用实践
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出,成为构建微服务的理想选择。本文将探讨Go语言在微服务架构中的应用实践,包括Go语言的特性如何适应微服务架构的需求,以及在实际开发中如何利用Go语言的特性来提高服务的性能和可维护性。我们将通过一个具体的案例分析,展示Go语言在微服务开发中的优势,并讨论在实际应用中可能遇到的挑战和解决方案。
|
4天前
|
Go
go语言中的 跳转语句
【11月更文挑战第4天】
12 4
|
4天前
|
JSON 安全 Go
Go语言中使用JWT鉴权、Token刷新完整示例,拿去直接用!
本文介绍了如何在 Go 语言中使用 Gin 框架实现 JWT 用户认证和安全保护。JWT(JSON Web Token)是一种轻量、高效的认证与授权解决方案,特别适合微服务架构。文章详细讲解了 JWT 的基本概念、结构以及如何在 Gin 中生成、解析和刷新 JWT。通过示例代码,展示了如何在实际项目中应用 JWT,确保用户身份验证和数据安全。完整代码可在 GitHub 仓库中查看。
17 1
|
8天前
|
Go 数据处理 API
Go语言在微服务架构中的应用与优势
本文摘要采用问答形式,以期提供更直接的信息获取方式。 Q1: 为什么选择Go语言进行微服务开发? A1: Go语言的并发模型、简洁的语法和高效的编译速度使其成为微服务架构的理想选择。 Q2: Go语言在微服务架构中有哪些优势? A2: 主要优势包括高性能、高并发处理能力、简洁的代码和强大的标准库。 Q3: 文章将如何展示Go语言在微服务中的应用? A3: 通过对比其他语言和展示Go语言在实际项目中的应用案例,来说明其在微服务架构中的优势。
|
8天前
|
Go 数据处理 调度
探索Go语言的并发模型:Goroutines与Channels的协同工作
在现代编程语言中,Go语言以其独特的并发模型脱颖而出。本文将深入探讨Go语言中的Goroutines和Channels,这两种机制如何协同工作以实现高效的并发处理。我们将通过实际代码示例,展示如何在Go程序中创建和管理Goroutines,以及如何使用Channels进行Goroutines之间的通信。此外,本文还将讨论在使用这些并发工具时可能遇到的常见问题及其解决方案,旨在为Go语言开发者提供一个全面的并发编程指南。
|
6天前
|
Go 调度 开发者
探索Go语言中的并发模式:goroutine与channel
在本文中,我们将深入探讨Go语言中的核心并发特性——goroutine和channel。不同于传统的并发模型,Go语言的并发机制以其简洁性和高效性著称。本文将通过实际代码示例,展示如何利用goroutine实现轻量级的并发执行,以及如何通过channel安全地在goroutine之间传递数据。摘要部分将概述这些概念,并提示读者本文将提供哪些具体的技术洞见。