当前位置: 首页 > news >正文

50周学习go语言:第五周 复合类型与词频统计

以下是第五周复合类型(数组、切片与映射)的详细学习内容,按照第四周的深度要求设计:


第五周:复合类型与词频统计


一、复合类型详解

1. 数组(Array)
// 声明与初始化
var arr1 [3]int           // 声明:[0 0 0]
arr2 := [3]string{"A", "B", "C"}  // 显式初始化
arr3 := [...]int{1,2,3}   // 编译器推断长度// 特性:
// - 固定长度(长度是类型的一部分)
// - 值传递(赋值/传参产生副本)
// - 内存连续分配// 操作示例:
arr := [5]int{10,20,30,40,50}
fmt.Println(arr[1])       // 20
arr[2] = 35               // 修改元素
fmt.Println(len(arr))     // 5(长度)
fmt.Println(cap(arr))     // 5(容量)
2. 切片(Slice)
// 创建方式
s1 := make([]int, 3, 5)   // 类型,长度,容量
s2 := []float64{1.1, 2.2} // 字面量
s3 := arr[1:3]            // 从数组切割// 特性:
// - 动态大小(自动扩容)
// - 引用类型(底层数组视图)
// - 包含ptr/len/cap三元组// 操作示例:
s := []int{10,20,30}
s = append(s, 40)         // 扩容追加
copy(s[1:], s[2:])        // 删除元素(20)
s = s[:len(s)-1]          // 新长度:[10 30 40]
3. 映射(Map)
// 初始化方式
m1 := make(map[string]int)
m2 := map[string]float64{"pi": 3.1415,"e":  2.7182,
}// 特性:
// - 无序键值对集合
// - 引用类型
// - 线程不安全// 操作示例:
ages := map[string]int{"Alice": 25,"Bob":   30,
}
ages["Charlie"] = 28      // 添加/修改
delete(ages, "Bob")       // 删除
if age, ok := ages["David"]; !ok {fmt.Println("不存在")
}

二、词频统计任务

需求分析
  1. 输入一段英文文本
  2. 输出单词出现频率(不区分大小写)
  3. 过滤标点符号和数字
  4. 支持并发处理(可选优化)
版本1:基础实现
func wordFrequency(text string) map[string]int {// 清理文本cleaner := func(r rune) rune {if unicode.IsLetter(r) {return unicode.ToLower(r)}return ' ' // 非字母转为空格}cleaned := strings.Map(cleaner, text)// 分割单词words := strings.Fields(cleaned)// 统计频率freq := make(map[string]int)for _, word := range words {freq[word]++}return freq
}
版本2:并发优化
func concurrentWordFrequency(text string) map[string]int {// 文本预处理(同上)cleaner := func(r rune) rune {/* 同版本1 */}cleaned := strings.Map(cleaner, text)words := strings.Fields(cleaned)// 并发处理var mu sync.Mutexvar wg sync.WaitGroupfreq := make(map[string]int)chunkSize := 1000for i := 0; i < len(words); i += chunkSize {end := i + chunkSizeif end > len(words) {end = len(words)}chunk := words[i:end]wg.Add(1)go func(words []string) {defer wg.Done()localFreq := make(map[string]int)for _, w := range words {localFreq[w]++}mu.Lock()for k, v := range localFreq {freq[k] += v}mu.Unlock()}(chunk)}wg.Wait()return freq
}

三、测试与性能

1. 表格驱动测试
func TestWordFrequency(t *testing.T) {tests := []struct {input stringwant  map[string]int}{{"Hello hello world",map[string]int{"hello":2, "world":1},},{"Go! 100% Go...",map[string]int{"go":2},},{"A man a plan a canal: Panama",map[string]int{"a":3, "man":1, "plan":1, "canal":1, "panama":1},},}for _, tt := range tests {got := wordFrequency(tt.input)if !reflect.DeepEqual(got, tt.want) {t.Errorf("输入 %q\n期望 %v\n实际 %v", tt.input, tt.want, got)}}
}
2. 性能基准测试
# 运行测试
go test -bench . -benchmem# 预期结果:
BenchmarkWordFrequency-8             5000    324521 ns/op   138920 B/op    502 allocs/op
BenchmarkConcurrent-8                8000    198745 ns/op   189654 B/op   1502 allocs/op

四、进阶技巧

1. 内存优化(预分配)
// 预估容量减少扩容
words := make([]string, 0, len(text)/5)  // 按平均单词长度5预估
freq := make(map[string]int, 1000)       // 预分配哈希表槽位
2. 正则表达式优化
// 使用正则分割更高效
re := regexp.MustCompile(`\W+`)
words := re.Split(strings.ToLower(text), -1)
3. 自定义排序输出
func sortedFrequency(freq map[string]int) []string {type pair struct {word  stringcount int}pairs := make([]pair, 0, len(freq))for k, v := range freq {pairs = append(pairs, pair{k, v})}sort.Slice(pairs, func(i, j int) bool {return pairs[i].count > pairs[j].count})result := make([]string, len(pairs))for i, p := range pairs {result[i] = fmt.Sprintf("%s:%d", p.word, p.count)}return result
}

五、扩展练习

  1. 停用词过滤

    func filterStopWords(freq map[string]int, stopWords map[string]struct{}) {for w := range freq {if _, exists := stopWords[w]; exists {delete(freq, w)}}
    }
    
  2. 词云生成器

    func generateWordCloud(freq map[string]int, size int) []string {// 根据频率生成不同字号标记// 示例:["GO(12)", "语言(8)", "并发(20)"]
    }
    

六、学习检查清单

  • 能正确定义数组、切片和映射
  • 理解切片扩容机制(容量翻倍策略)
  • 会使用sync.Mutex处理并发map访问
  • 能解释数组与切片的底层关系
  • 理解map的哈希表实现原理
  • 会进行切片的内存预分配优化
  • 能处理Unicode字符的文本清洗
  • 会编写并发安全的统计程序

通过本学习内容,您将掌握Go语言核心复合类型的特性和高效使用方法,并能够根据实际场景选择最佳数据结构。建议:

  1. 尝试处理1GB以上的大文本文件
  2. 比较不同分块策略对并发版本的影响
  3. 使用pprof分析内存分配热点
  4. 实现扩展练习中的词云可视化功能

相关文章:

50周学习go语言:第五周 复合类型与词频统计

以下是第五周复合类型&#xff08;数组、切片与映射&#xff09;的详细学习内容&#xff0c;按照第四周的深度要求设计&#xff1a; 第五周&#xff1a;复合类型与词频统计 一、复合类型详解 1. 数组&#xff08;Array&#xff09; // 声明与初始化 var arr1 [3]int …...

HTTP非流式请求 vs HTTP流式请求

文章目录 HTTP 非流式请求 vs 流式请求一、核心区别 服务端代码示例&#xff08;Node.js/Express&#xff09;非流式请求处理流式请求处理 客户端请求示例非流式请求&#xff08;浏览器fetch&#xff09;流式请求处理&#xff08;浏览器fetch&#xff09; Python客户端示例&…...

深圳南柯电子|医疗设备EMC测试整改检测:零到一,保障医疗安全

在当今医疗科技飞速发展的时代&#xff0c;医疗设备的电磁兼容性&#xff08;EMC&#xff09;已成为确保其安全、有效运行的关键要素之一。EMC测试整改检测不仅关乎设备的性能稳定性&#xff0c;更是保障患者安全、避免电磁干扰引发医疗事故的重要措施。 一、医疗设备EMC测试整…...

详解:事务注解 @Transactional

创作内容丰富的干货文章很费心力&#xff0c;感谢点过此文章的读者&#xff0c;点一个关注鼓励一下作者&#xff0c;激励他分享更多的精彩好文&#xff0c;谢谢大家&#xff01; Transactional 是 Spring Framework 中常用的注解之一&#xff0c;它可以被用于管理事务。通过使…...

【虚拟仪器技术】labview操作指南和虚拟仪器技术习题答案(一)

今天是2025年2月24日&#xff0c;画的是fate/Grand Order里面的阿尔托莉雅.卡斯特&#xff0c;武内老师的画。 目录 第1章 第2章 第3章 第4章 第5章 关注作者了解更多 我的其他CSDN专栏 毕业设计 求职面试 大学英语 过程控制系统 工程测试技术 虚拟仪器技术 可编程…...

在Linux桌面上创建Idea启动快捷方式

1、在桌面新建idea.desktop vim idea.desktop [Desktop Entry] EncodingUTF-8 NameIntelliJ IDEA CommentIntelliJ IDEA Exec/home/software/idea-2021/bin/idea.sh Icon/home/software/idea-2021/bin/idea.svg Terminalfalse TypeApplication CategoriesApplication;Developm…...

渗透测试(WAF过滤information_schema库的绕过,sqllib-46关,海洋cms9版本的注入)

1.sqlin-lib 46关 打开网站配置文件发现 此网站的对ID进行了排序&#xff0c;我们可以知道&#xff0c;order by接不了union &#xff0c;那我们可以通过测试sort&#xff0c;rond等函数&#xff0c;观察网页的反馈来判断我们的盲注是否正确 我们发现 当参数有sort来排序时&…...

Unity基础——资源导出分享为Unity Package

一.选中要打包的文件夹&#xff0c;右击&#xff0c;点击Exporting package 二.勾选 Include Dependencies&#xff0c;点击Export Include Dependencies&#xff1a;代表是否包含资源依赖的选项 三.选择保存的位置&#xff0c;即可生成Unity package 最终形成文件&#xff1a…...

C语言【指针篇】(三)

C语言【指针篇】&#xff08;三&#xff09; 前言正文1. 数组名的理解2. 使用指针访问数组3. 一维数组传参的本质4. 冒泡排序5. 二级指针6. 指针数组7. 指针数组模拟二维数组 总结 前言 本文主要基于前面对指针的掌握&#xff0c;进一步学习&#xff1a;数组名的理解、使用指针…...

DevSecOps普及:安全与开发运维的深度融合

一、引言 随着软件开发模式的演进&#xff0c;DevOps已成为现代软件工程的主流实践。然而&#xff0c;在传统的DevOps流程中&#xff0c;安全往往被视为开发和运维之外的额外环节&#xff0c;导致安全漏洞在产品交付后才被发现&#xff0c;增加了修复成本和风险。为了解决这一…...

【JAVA-数据结构】Map和Set

上一篇我们聊到了排序相关内容&#xff0c;这一篇我们对Map和Set进行一系列说明&#xff0c;大家自取。 1.搜索树 1.1 概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树不为空&#xff0c;则左子树上所有节…...

从 0 到 1,用 Python 构建超实用 Web 实时聊天应用

从 0 到 1&#xff0c;用 Python 构建超实用 Web 实时聊天应用 本文深入剖析如何运用 Python 的 Flask 框架与 SocketIO 扩展&#xff0c;搭建一个功能完备的 Web 实时聊天应用。从环境搭建、前后端代码实现&#xff0c;到最终运行展示&#xff0c;逐步拆解关键步骤&#xff0…...

轻松搭建:使用Anaconda创建虚拟环境并在PyCharm中配置

一、使用Anaconda创建虚拟环境 1. 安装Anaconda 2..conda常用的命令 3. 创建虚拟环境-以搭建MachineVision为例 4. 激活虚拟环境 5. 安装依赖包 二、PyCharm配置环境 在进行Python项目开发时&#xff0c;合理的环境管理是必不可少的&#xff0c;特别是当你在多个项目中…...

【新人系列】Python 入门专栏合集

✍ 个人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4dd; 专栏地址&#xff1a;https://blog.csdn.net/newin2020/category_12801353.html &#x1f4e3; 专栏定位&#xff1a;为 0 基础刚入门 Python 的小伙伴提供详细的讲解&#xff0c;也欢迎大佬们…...

linux ununtu安装mysql 怎么在my.cnf文件里临时配置 无密码登录

在 Ubuntu 中&#xff0c;若需通过修改 my.cnf 临时禁用 MySQL 的密码验证&#xff08;例如忘记 root 密码需要重置&#xff09;&#xff0c;可以通过添加 skip-grant-tables 选项实现。以下是具体步骤&#xff1a; 步骤 1&#xff1a;编辑 MySQL 配置文件 1. 打开 MySQL 配置…...

git,bash - 从一个远端git库只下载一个文件的方法

文章目录 git,bash - 从一个远端git库只下载一个文件的方法概述笔记写一个bash脚本来自动下载get_github_raw_file_from_url.shreanme_file.shfind_key_value.sh执行命令 END git,bash - 从一个远端git库只下载一个文件的方法 概述 github上有很多大佬上传了电子书库&#xf…...

python生成的exe文件防止反编译(pyinstaller加密)

python生成的exe文件可以轻松的被破解&#xff0c;为了防止反编译&#xff0c;知乎友友们给出了很多不同的见解&#xff0c;其中主流的回答是pyinstaller加密和niutka打包python&#xff0c;本篇介绍的方法是第一种&#xff0c;pyinstaller打包的时候进行加密&#xff0c;防破解…...

Android移动应用开发实践-1-下载安装和简单使用Android Studio 3.5.2版本(频频出错)

一、下载安装 1.Android Studio3.5.2下载地址&#xff1a;Android Studio3.5.2下载地址 其他版本下载地址&#xff1a;其他版本下载地址 2.安装教程&#xff08;可以多找几个看看&#xff09; 安装 | 手把手教你Android studio 3.5.2安装&#xff08;安装教程&#xff09;_a…...

Android Audio实战——音频相关基础概念(附)

Android Audio 开发其实就是媒体源数字化的过程,通过将声波波形信号通过 ADC 转换成计算机支持的二进制的过程叫做音频采样 (Audio Sampling)。采样 (Sampling) 的核心是把连续的模拟信号转换成离散的数字信号。 一、声音的属性 1、响度 (Loudness) 响度是指人类可以感知到的…...

5分钟使用Docker部署Paint Board快速打造专属在线画板应用

文章目录 前言1.关于Paint Board2.本地部署paint-board3.使用Paint Board4.cpolar内网穿透工具安装5.创建远程连接公网地址6.固定Paint Board公网地址 &#x1f4a1; 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

Vue ③-生命周期 || 脚手架

生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09; 什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a; 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...

C++实现分布式网络通信框架RPC(2)——rpc发布端

有了上篇文章的项目的基本知识的了解&#xff0c;现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理

在城市的某个角落&#xff0c;一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延&#xff0c;滚滚浓烟弥漫开来&#xff0c;周围群众的生命财产安全受到严重威胁。就在这千钧一发之际&#xff0c;消防救援队伍迅速行动&#xff0c;而豪越科技消防一体化安全管控平台构建的消防“…...

高端性能封装正在突破性能壁垒,其芯片集成技术助力人工智能革命。

2024 年&#xff0c;高端封装市场规模为 80 亿美元&#xff0c;预计到 2030 年将超过 280 亿美元&#xff0c;2024-2030 年复合年增长率为 23%。 细分到各个终端市场&#xff0c;最大的高端性能封装市场是“电信和基础设施”&#xff0c;2024 年该市场创造了超过 67% 的收入。…...