要让单词计数更准确,需统一大小写并处理标点符号。1. 使用strings.tolower()将单词统一为小写,避免“go”与“go”被误判为不同词;2. 用regexp.mustcompile([^a-za-z0-9]+)替换非字母数字字符为空格,再通过strings.fields()分割单词,确保“hello,”和“world.”被正确识别为“hello”和“world”;3. 可选使用strings.fieldsfunc()自定义分隔符逻辑,以灵活处理连字符或特殊字符,提升多语言支持能力。

用Golang实现一个单词计数器,核心在于读取文本内容,将文本拆分成独立的单词,然后利用Go语言的
map

package main
import (
"bufio"
"fmt"
"io"
"os"
"regexp"
"sort"
"strings"
)
// WordCountResult 结构体用于存储单词及其计数
type WordCountResult struct {
Word string
Count int
}
// ByCount 实现sort.Interface,用于按计数降序排序
type ByCount []WordCountResult
func (a ByCount) Len() int { return len(a) }
func (a ByCount) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByCount) Less(i, j int) bool { return a[i].Count > a[j].Count } // 降序
// CountWords 从io.Reader中读取文本并统计单词频率
func CountWords(reader io.Reader) (map[string]int, error) {
wordCounts := make(map[string]int)
scanner := bufio.NewScanner(reader)
// 使用正则表达式匹配字母和数字,排除标点符号
// 这里我倾向于用一个稍微宽泛的匹配,然后把非字母数字的字符替换掉,
// 这样可以处理一些连字符或特殊字符的情况,但基础版就用简单的
// [a-zA-Z0-9]+ 就可以了。为了更通用,我用一个更灵活的方式。
// 这里我们直接用 FieldsFunc,它更Go-idiomatic。
// 但为了简单和通用性,我们先用正则清理。
reg := regexp.MustCompile(`[^a-zA-Z0-9]+`) // 匹配非字母数字字符
for scanner.Scan() {
line := scanner.Text()
// 将所有非字母数字字符替换为空格,然后按空格分割
cleanedLine := reg.ReplaceAllString(line, " ")
words := strings.Fields(cleanedLine) // strings.Fields 会按空白符分割
for _, word := range words {
word = strings.ToLower(word) // 统一转为小写
if len(word) > 0 { // 避免空字符串
wordCounts[word]++
}
}
}
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("读取输入时发生错误: %w", err)
}
return wordCounts, nil
}
func main() {
// 示例:从标准输入读取
fmt.Println("请输入文本(输入空行并按Ctrl+D或Ctrl+Z结束):")
counts, err := CountWords(os.Stdin)
if err != nil {
fmt.Fprintf(os.Stderr, "错误: %v\n", err)
os.Exit(1)
}
// 将结果转换为切片以便排序
var results []WordCountResult
for word, count := range counts {
results = append(results, WordCountResult{Word: word, Count: count})
}
// 排序
sort.Sort(ByCount(results))
// 打印结果
fmt.Println("\n--- 单词计数结果 ---")
for _, res := range results {
fmt.Printf("%-20s %d\n", res.Word, res.Count)
}
}要让单词计数更准确,处理文本中的标点符号和大小写是绕不过去的坎。这就像你在数苹果,结果发现有些苹果带着泥巴,有些是红的有些是青的,你总得先把泥巴洗掉,然后把所有苹果都当成苹果来数,而不是区分红苹果和青苹果。
在Golang中,我们通常会采取几个步骤来“清洗”文本:
立即学习“go语言免费学习笔记(深入)”;

strings.ToLower()
strings.ToUpper()
regexp
regexp.MustCompile(
)
\p{L}\p{N}[a-zA-Z0-9]
strings.Fields()
strings.FieldsFunc()
strings.Fields
FieldsFunc
当处理的文件不是几KB而是几GB甚至几十GB时,性能和内存就成了不得不面对的挑战。我曾经在处理日志文件时遇到过内存飙升的问题,那感觉就像眼睁睁看着你的程序把所有可用的RAM都吞噬掉。
Golang在这方面有一些天然的优势,但也需要我们合理利用:

bufio.Scanner
ioutil.ReadFile
os.ReadFile
bufio.Scanner
map
map[string]int
map
map
map
sync.Mutex
sync.Map
map
bufio.Scanner
我通常会先用
bufio.Scanner
一个基础的单词计数器只是个起点,它还有很多可以扩展的有趣功能,让它变成一个更强大的文本分析小助手。这就像你有了把刀,除了切菜,还能削水果、雕刻。
我个人在做文本分析时,最常用到的就是停用词过滤和Top N显示,这两点能最快地让我从海量文本中提取出有价值的信息。当然,如果数据量大,导出CSV再用Excel或Python处理也是个不错的选择。
以上就是如何用Golang实现单词计数器 开发统计文本词频的小工具的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号