golang键盘布局智能纠错与替代建议插件库TySug的使用
Golang 键盘布局智能纠错与替代建议插件库 TySug 的使用
TySug 是一个键盘布局感知的替代单词建议器集合,可以作为库和 Web 服务使用。
主要支持用例是针对短流行词列表(如域名)帮助纠正拼写错误,这对于防止电子邮件地址中的拼写错误、检测垃圾邮件、网络钓鱼(Typosquatting)等非常有用。
快速开始
如果你已安装 Docker,可以快速运行:
docker run --rm -it dynom/tysug:latest
在另一个终端中运行:
curl -s "http://127.0.0.1:1337/list/domains" --data-binary '{"input": "gmail.co"}'
作为 Web 服务使用
Web 服务使用 Jaro-Winkler 算法计算相似度:
{
"result": "gmail.com",
"score": 0.9777777777777777,
"exact_match": false
}
作为库使用
TySug 是一组独立的包,每个库都有详细的 README 说明。
基本用法
import "github.com/Dynom/TySug/finder"
referenceList := []string{"example", "amplifier", "ample"}
ts := finder.New(referenceList, finder.WithAlgorithm(myAlgorithm))
alt, score, exact := ts.Find("exampel")
// alt = example
// score = 0.9714285714285714
// exact = false (不在我们的参考列表中完全匹配)
使用不同算法
如果你想使用不同的算法,只需将算法包装在 finder.Algorithm
兼容类型中并传递给 Finder。
可能的算法选择:
- Levenshtein
- Damerau-Levenshtein
- LCS
- q-gram
- Cosine
- Jaccard
- Jaro / Jaro-Winkler
- Smith-Waterman
- Sift4
处理置信度
添加自己的算法时,需要自己处理"置信度"元素:
var someAlgorithm finder.AlgWrapper = func(a, b string) float64 {
// 结果是达到相等所需的步骤数
// 像 Jaro 这样的算法产生 0.0 到 1.0 之间的值
score := someAlgorithm.CalculateDistance(a, b)
// 找到最长的字符串
var ml = len(b)
if len(a) >= len(b) {
ml = len(a)
}
// 这会引入偏差。较长的输入比较短的输入略有优势,导致删除的权重较小。
return 1 - (score / float64(ml))
}
sug := finder.New([]list, finder.WithAlgorithm(someAlgorithm))
bestMatch, score := sug.Find(input)
// 这里对于长度为 10 的字符串,有 2 个突变,分数可能是 0.8
示例
查找常见电子邮件域名拼写错误
func SuggestAlternative(email string, domains []string) (string, float64) {
i := strings.LastIndex(email, "@")
if 0 >= i || i >= len(email) {
return email, 0
}
// 提取本地部分和域名部分
localPart := email[:i]
hostname := email[i+1:]
sug, _ := finder.New(domains)
alternative, score, exact := sug.Find(hostname)
if exact || score > 0.9 {
combined := localPart + "@" + alternative
return combined, score
}
return email, score
}
参考列表
参考列表是包含已知/批准单词的列表。TySug 的 Web 服务未针对处理大型列表进行优化,而是针对"有主见的"列表。
键盘布局感知
TySug 的 Web 服务具有键盘布局感知能力。这意味着当输入是 ‘bee5’ 且参考列表包含单词 ‘beer’ 和 ‘beek’ 时,在 Query-US 键盘上会优先选择 ‘beer’。
拼写错误类型
处理拼写错误很复杂且高度依赖于上下文:
- 原子拼写错误 - 输入一个(上下文)不正确但拼写正确的单词
- 故意拼写错误 - 输入 “teh” 而不是 “the”
- 标记拼写错误 - 故意的"拼写错误"
贡献指南
在贡献之前,请创建一个问题描述你想要贡献的内容。任何贡献都必须以 PR 的形式提供,并且 CI 构建必须通过。
更多关于golang键盘布局智能纠错与替代建议插件库TySug的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang键盘布局智能纠错与替代建议插件库TySug的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang键盘布局智能纠错与替代建议插件库TySug使用指南
TySug是一个用于Golang的键盘布局感知的字符串相似度计算和智能纠错库,它能够根据常见的键盘布局(如QWERTY、AZERTY等)提供拼写纠正和替代建议。
主要特性
- 键盘布局感知的字符串相似度计算
- 拼写错误检测与纠正
- 提供替代建议列表
- 支持自定义键盘布局
- 轻量级且易于集成
安装
go get github.com/Dynom/TySug
基本使用示例
package main
import (
"fmt"
"github.com/Dynom/TySug/finder"
)
func main() {
// 准备参考列表(字典)
referenceList := []string{"apple", "banana", "orange", "pear", "peach"}
// 创建查找器实例
f := finder.New(referenceList, finder.WithAlgorithm(finder.AlgorithmTySug))
// 测试拼写错误的输入
testCases := []string{"appl3", "bannna", "oramge", "pear", "peahc"}
for _, input := range testCases {
suggestions, _ := f.Find(input)
fmt.Printf("Input: %s -> Best match: %s\n", input, suggestions.Top())
}
}
高级功能
1. 自定义键盘布局
package main
import (
"fmt"
"github.com/Dynom/TySug/finder"
"github.com/Dynom/TySug/keyboard"
)
func main() {
// 自定义键盘布局
customLayout := keyboard.QwertyUS.Layout()
// 修改布局,例如将'z'和'y'交换(德语键盘)
customLayout['z'], customLayout['y'] = customLayout['y'], customLayout['z']
// 使用自定义布局创建查找器
f := finder.New(
[]string{"apple", "banana", "orange"},
finder.WithAlgorithm(finder.AlgorithmTySug),
finder.WithKeyboardLayout(customLayout),
)
result, _ := f.Find("appze") // 在修改后的布局中,'z'接近'y'
fmt.Println(result.Top()) // 可能输出 "apple"
}
2. 获取多个建议
package main
import (
"fmt"
"github.com/Dynom/TySug/finder"
)
func main() {
f := finder.New([]string{"hello", "world", "golang", "good", "google"})
// 获取前3个建议
input := "goo"
suggestions, _ := f.Find(input, finder.WithLimit(3))
fmt.Printf("Suggestions for '%s':\n", input)
for i, sug := range suggestions {
fmt.Printf("%d. %s (score: %.2f)\n", i+1, sug.Term, sug.Score)
}
}
3. 结合其他算法
package main
import (
"fmt"
"github.com/Dynom/TySug/finder"
"github.com/Dynom/TySug/algorithm"
)
func main() {
// 创建自定义算法组合
comboAlgo := algorithm.NewCombo().
AddAlgorithm(algorithm.NewJaroWinkler()).
AddAlgorithm(algorithm.NewLevenshtein())
f := finder.New(
[]string{"algorithm", "function", "variable", "constant"},
finder.WithAlgorithm(comboAlgo),
)
input := "functon"
suggestion, _ := f.Find(input)
fmt.Printf("Did you mean '%s' instead of '%s'?\n", suggestion.Top(), input)
}
实际应用场景
1. 搜索建议
package main
import (
"fmt"
"github.com/Dynom/TySug/finder"
)
type SearchService struct {
finder *finder.Instance
}
func NewSearchService(products []string) *SearchService {
return &SearchService{
finder: finder.New(products, finder.WithAlgorithm(finder.AlgorithmTySug)),
}
}
func (s *SearchService) GetSearchSuggestions(query string) []string {
result, err := s.finder.Find(query, finder.WithLimit(5))
if err != nil {
return nil
}
var suggestions []string
for _, sug := range result {
suggestions = append(suggestions, sug.Term)
}
return suggestions
}
func main() {
products := []string{"iPhone", "MacBook", "iPad", "iMac", "Apple Watch"}
service := NewSearchService(products)
fmt.Println(service.GetSearchSuggestions("iPhonr")) // [iPhone iPad iMac]
fmt.Println(service.GetSearchSuggestions("MakBook")) // [MacBook]
}
2. 表单输入验证
package main
import (
"fmt"
"github.com/Dynom/TySug/finder"
)
var countryFinder *finder.Instance
func init() {
countries := []string{"United States", "Canada", "Mexico", "Brazil", "Germany"}
countryFinder = finder.New(countries, finder.WithAlgorithm(finder.AlgorithmTySug))
}
func ValidateCountryInput(input string) (string, bool) {
suggestion, err := countryFinder.Find(input)
if err != nil {
return "", false
}
// 如果匹配分数高于阈值,则认为是正确的
if suggestion.TopScore() > 0.8 {
return suggestion.Top(), true
}
return "", false
}
func main() {
input := "Unted States"
if corrected, ok := ValidateCountryInput(input); ok {
fmt.Printf("Did you mean: %s?\n", corrected)
} else {
fmt.Println("Country not recognized")
}
}
性能优化技巧
- 预加载字典:在服务启动时加载参考列表,避免每次请求都重新初始化
- 限制建议数量:使用
WithLimit
选项限制返回的建议数量 - 缓存结果:对常见输入进行缓存
- 并行处理:对于大型字典,可以考虑并行处理
package main
import (
"fmt"
"sync"
"github.com/Dynom/TySug/finder"
)
type CachedFinder struct {
finder *finder.Instance
cache map[string]finder.Suggestions
mu sync.RWMutex
}
func NewCachedFinder(reference []string) *CachedFinder {
return &CachedFinder{
finder: finder.New(reference),
cache: make(map[string]finder.Suggestions),
}
}
func (c *CachedFinder) Find(input string) (finder.Suggestions, error) {
c.mu.RLock()
if cached, exists := c.cache[input]; exists {
c.mu.RUnlock()
return cached, nil
}
c.mu.RUnlock()
result, err := c.finder.Find(input)
if err != nil {
return nil, err
}
c.mu.Lock()
c.cache[input] = result
c.mu.Unlock()
return result, nil
}
func main() {
cf := NewCachedFinder([]string{"apple", "banana", "orange"})
result, _ := cf.Find("appel")
fmt.Println(result.Top())
}
总结
TySug是一个功能强大且灵活的Golang库,特别适合需要处理用户输入纠正和建议的场景。通过键盘布局感知的算法,它能够更准确地检测和纠正拼写错误,特别是那些由于键盘按键相邻而导致的常见错误。
该库的模块化设计允许开发者根据需要自定义键盘布局、相似度算法和各种选项,使其能够适应各种不同的应用场景。无论是构建搜索引擎的自动建议功能,还是实现表单输入的智能验证,TySug都能提供有效的解决方案。
通过合理使用缓存和性能优化技巧,TySug可以轻松集成到高性能应用中,为用户提供流畅的拼写纠正体验。