Go词频教程展示了如何在Golang中计算词频。
$ go version go version go1.18.1 linux/amd64
我们使用Go版本1.18。
我们的示例仅适用于拉丁词,并且专门针对分析圣经。
$ wget https://raw.githubusercontent.com/janbodnar/data/main/the-king-james-bible.txt
我们使用钦定版圣经。
为了将文本切割成单词,我们使用Go的strings.FieldsFunc和正则表达式。
Go词频示例I
FieldsFunc函数在每次运行满足提供函数的Unicodecode点时拆分字符串,并返回一个切片数组。
package main
import (
"fmt"
"io/ioutil"
"log"
"sort"
"strings"
)
func main() {
fileName := "the-king-james-bible.txt"
bs, err := ioutil.ReadFile(fileName)
if err != nil {
log.Fatal(err)
}
text := string(bs)
fields := strings.FieldsFunc(text, func(r rune) bool {
return !('a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' || r == '\'')
})
wordsCount := make(map[string]int)
for _, field := range fields {
wordsCount[field]++
}
keys := make([]string, 0, len(wordsCount))
for key := range wordsCount {
keys = append(keys, key)
}
sort.Slice(keys, func(i, j int) bool {
return wordsCount[keys[i]] > wordsCount[keys[j]]
})
for idx, key := range keys {
fmt.Printf("%s %d\n", key, wordsCount[key])
if idx == 10 {
break
}
}
}
我们计算KingJames圣经中单词的出现频率。
fields := strings.FieldsFunc(text, func(r rune) bool {
return !('a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' || r == '\'')
})
FieldsFunc按非字母和撇号的字符剪切文本。这也将忽略所有节号。
wordsCount := make(map[string]int)
for _, field := range fields {
wordsCount[field]++
}
每个单词及其频率都存储在wordsCount映射中。
keys := make([]string, 0, len(wordsCount))
for key := range wordsCount {
keys = append(keys, key)
}
sort.Slice(keys, func(i, j int) bool {
return wordsCount[keys[i]] > wordsCount[keys[j]]
})
为了按频率对单词进行排序,我们创建了一个新的keys切片。我们将所有单词放在那里并按它们的频率值对它们进行排序。
for idx, key := range keys {
fmt.Printf("%s %d\n", key, wordsCount[key])
if idx == 10 {
break
}
}
我们打印出圣经中最常用的前十个单词。
$ go run word_freq.go the 62103 and 38848 of 34478 to 13400 And 12846 that 12576 in 12331 shall 9760 he 9665 unto 8942 I 8854
Go词频例子二
在第二个示例中,我们使用正则表达式将文本分成单词。
package main
import (
"fmt"
"io/ioutil"
"log"
"regexp"
"sort"
)
type WordFreq struct {
word string
freq int
}
func (p WordFreq) String() string {
return fmt.Sprintf("%s %d", p.word, p.freq)
}
func main() {
fileName := "the-king-james-bible.txt"
reg := regexp.MustCompile("[a-zA-Z']+")
bs, err := ioutil.ReadFile(fileName)
if err != nil {
log.Fatal(err)
}
text := string(bs)
matches := reg.FindAllString(text, -1)
words := make(map[string]int)
for _, match := range matches {
words[match]++
}
var wordFreqs []WordFreq
for k, v := range words {
wordFreqs = append(wordFreqs, WordFreq{k, v})
}
sort.Slice(wordFreqs, func(i, j int) bool {
return wordFreqs[i].freq > wordFreqs[j].freq
})
for i := 0; i < 10; i++ {
fmt.Println(wordFreqs[i])
}
}
我们将单词及其频率存储在WordFreq结构中。
reg := regexp.MustCompile("[a-zA-Z']+")
在我们的正则表达式中,一个或多个字母字符或撇号构成一个词。
matches := reg.FindAllString(text, -1)
FindAllString函数返回表达式的所有连续匹配项的一部分。
words := make(map[string]int)
for _, match := range matches {
words[match]++
}
我们检查匹配项并计算它们在文件中的频率。单词及其出现次数存储在wordsmap中。
var wordFreqs []WordFreq
for k, v := range words {
wordFreqs = append(wordFreqs, WordFreq{k, v})
}
我们从words映射中构建了一片WordFreq结构。
sort.Slice(wordFreqs, func(i, j int) bool {
return wordFreqs[i].freq > wordFreqs[j].freq
})
我们按freq字段对wordFreqs切片进行排序。
for i := 0; i < 10; i++ {
fmt.Println(wordFreqs[i])
}
我们打印前十个最常见的单词。
围棋词频例子三
在下一个示例中,我们还使用正则表达式。
package main
import (
"fmt"
"io/ioutil"
"log"
"regexp"
"sort"
)
type WordFreq struct {
word string
freq int
}
func (p WordFreq) String() string {
return fmt.Sprintf("%s %d", p.word, p.freq)
}
type byFreq []WordFreq
func (a byFreq) Len() int { return len(a) }
func (a byFreq) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a byFreq) Less(i, j int) bool { return a[i].freq < a[j].freq }
func main() {
fileName := "the-king-james-bible.txt"
bs, err := ioutil.ReadFile(fileName)
if err != nil {
log.Fatal(err)
}
text := string(bs)
re := regexp.MustCompile("[a-zA-Z']+")
matches := re.FindAllString(text, -1)
words := make(map[string]int)
for _, match := range matches {
words[match]++
}
var wordFreqs []WordFreq
for k, v := range words {
wordFreqs = append(wordFreqs, WordFreq{k, v})
}
sort.Sort(sort.Reverse(byFreq(wordFreqs)))
for i := 0; i < 10; i++ {
fmt.Printf("%v\n", wordFreqs[i])
}
}
此示例还实现了自定义排序接口。
type byFreq []WordFreq
func (a byFreq) Len() int { return len(a) }
func (a byFreq) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a byFreq) Less(i, j int) bool { return a[i].freq < a[j].freq }
我们根据freq字段为[]WordFreq实现了sort.Interface。
sort.Sort(sort.Reverse(byFreq(wordFreqs)))
要按降序对WordFreq结构进行排序,我们使用sort.Reverse函数。
在本教程中,我们计算了钦定版圣经中的词频。
列出所有Go教程。
