golang字符串比较与编辑距离算法插件库go-edlib的使用

Golang字符串比较与编辑距离算法插件库go-edlib的使用

介绍

Go-edlib是一个Golang开源库,包含了多种编辑距离和字符串比较算法,并支持Unicode字符。该库具有100%的测试覆盖率。

功能特性

  • Levenshtein距离
  • LCS(最长公共子序列)及其编辑距离、回溯和差异功能
  • Hamming距离
  • Damerau-Levenshtein距离(包含OSA和相邻转置算法)
  • Jaro & Jaro-Winkler相似度算法
  • 余弦相似度
  • Jaccard指数
  • QGram
  • Sorensen-Dice系数
  • 基于所有可用编辑距离算法的相似度百分比计算
  • 基于编辑距离的模糊搜索功能(支持单结果和多结果输出)
  • Unicode兼容

安装

在项目目录下运行:

go get github.com/hbollon/go-edlib

然后在代码中导入:

import (
    "github.com/hbollon/go-edlib"
)

使用示例

1. 计算两个字符串的相似度

res, err := edlib.StringsSimilarity("string1", "string2", edlib.Levenshtein)
if err != nil {
    fmt.Println(err)
} else {
    fmt.Printf("Similarity: %f", res)
}

2. 执行模糊搜索

2.1 无阈值的最匹配结果

strList := []string{"test", "tester", "tests", "testers", "testing", "tsting", "sting"}
res, err := edlib.FuzzySearch("testnig", strList, edlib.Levenshtein)
if err != nil {
    fmt.Println(err)
} else {
    fmt.Printf("Result: %s", res)
}

2.2 带阈值的最匹配结果

strList := []string{"test", "tester", "tests", "testers", "testing", "tsting", "sting"}
res, err := edlib.FuzzySearchThreshold("testnig", strList, 0.7, edlib.Levenshtein)
if err != nil {
    fmt.Println(err)
} else {
    fmt.Printf("Result: %s", res)
}

3. 获取原始编辑距离

res := edlib.LevenshteinDistance("kitten", "sitting")
fmt.Printf("Result: %d", res)

4. LCS相关操作

4.1 计算LCS长度

lcs := edlib.LCS("ABCD", "ACBAD")
fmt.Printf("Length of their LCS: %d", lcs)

4.2 回溯LCS

res, err := edlib.LCSBacktrack("ABCD", "ACBAD")
if err != nil {
    fmt.Println(err)
} else {
    fmt.Printf("LCS: %s", res)
}

4.3 获取LCS差异

res, err := edlib.LCSDiff("computer", "houseboat")
if err != nil {
    fmt.Println(err)
} else {
    fmt.Printf("LCS Diff: \n%s\n%s", res[0], res[1])
}

完整示例

package main

import (
	"fmt"
	"github.com/hbollon/go-edlib"
	"strings"
)

func main() {
	// 1. 字符串相似度计算
	similarity, err := edlib.StringsSimilarity("hello", "hallo", edlib.Levenshtein)
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Printf("Similarity between 'hello' and 'hallo': %.2f\n", similarity)
	}

	// 2. 模糊搜索
	strList := []string{"test", "tester", "tests", "testers", "testing", "tsting", "sting"}
	
	// 2.1 无阈值搜索
	result, err := edlib.FuzzySearch("testnig", strList, edlib.Levenshtein)
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Printf("Fuzzy search result for 'testnig': %s\n", result)
	}
	
	// 2.2 带阈值搜索
	result, err = edlib.FuzzySearchThreshold("testnig", strList, 0.7, edlib.Levenshtein)
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Printf("Fuzzy search with threshold 0.7: %s\n", result)
	}
	
	// 3. 编辑距离计算
	levDist := edlib.LevenshteinDistance("kitten", "sitting")
	fmt.Printf("Levenshtein distance between 'kitten' and 'sitting': %d\n", levDist)
	
	// 4. LCS操作
	// 4.1 LCS长度
	lcsLen := edlib.LCS("ABCD", "ACBAD")
	fmt.Printf("LCS length between 'ABCD' and 'ACBAD': %d\n", lcsLen)
	
	// 4.2 LCS回溯
	lcs, err := edlib.LCSBacktrack("ABCD", "ACBAD")
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Printf("LCS between 'ABCD' and 'ACBAD': %s\n", lcs)
	}
	
	// 4.3 LCS差异
	diff, err := edlib.LCSDiff("computer", "houseboat")
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println("LCS Diff between 'computer' and 'houseboat':")
		fmt.Println(diff[0])
		fmt.Println(diff[1])
	}
	
	// 5. 多结果模糊搜索
	results, err := edlib.FuzzySearchSet("testnig", strList, 3, edlib.Levenshtein)
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Printf("Top 3 matches for 'testnig': %s\n", strings.Join(results, ", "))
	}
}

作者

👤 Hugo Bollon

许可证

该项目采用MIT许可证授权。


更多关于golang字符串比较与编辑距离算法插件库go-edlib的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang字符串比较与编辑距离算法插件库go-edlib的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Go语言字符串比较与编辑距离算法:go-edlib库使用指南

字符串比较基础

在Go语言中,最基本的字符串比较方式是使用==运算符或strings.Compare()函数:

package main

import (
	"fmt"
	"strings"
)

func main() {
	str1 := "hello"
	str2 := "world"
	str3 := "hello"

	// 使用==比较
	fmt.Println(str1 == str2) // false
	fmt.Println(str1 == str3) // true

	// 使用strings.Compare
	fmt.Println(strings.Compare(str1, str2)) // -1 (str1 < str2)
	fmt.Println(strings.Compare(str1, str3)) // 0 (相等)
}

go-edlib库介绍

go-edlib是一个强大的字符串比较和模糊匹配库,提供了多种字符串相似度算法:

  • Levenshtein距离(编辑距离)
  • Damerau-Levenshtein距离
  • Jaro-Winkler相似度
  • 余弦相似度
  • Jaccard相似度
  • Sorensen-Dice相似度
  • 汉明距离

安装go-edlib

go get github.com/hbollon/go-edlib

基本使用示例

1. 计算字符串相似度

package main

import (
	"fmt"
	"github.com/hbollon/go-edlib"
)

func main() {
	str1 := "kitten"
	str2 := "sitting"

	// 计算Levenshtein距离
	levDist, err := goedlib.LevenshteinDistance(str1, str2)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Levenshtein距离: %d\n", levDist) // 3

	// 计算相似度(0-1)
	similarity, err := goedlib.StringSimilarity(str1, str2, goedlib.Levenshtein)
	if err != nil {
		panic(err)
	}
	fmt.Printf("相似度: %.2f\n", similarity) // 0.57
}

2. 使用不同算法比较

func compareWithDifferentAlgorithms() {
	str1 := "apple"
	str2 := "appel"

	// Jaro-Winkler相似度
	jw, _ := goedlib.StringSimilarity(str1, str2, goedlib.JaroWinkler)
	fmt.Printf("Jaro-Winkler: %.2f\n", jw) // 0.96

	// 余弦相似度
	cos, _ := goedlib.StringSimilarity(str1, str2, goedlib.Cosine)
	fmt.Printf("余弦相似度: %.2f\n", cos) // 0.80

	// Jaccard相似度
	jac, _ := goedlib.StringSimilarity(str1, str2, goedlib.Jaccard)
	fmt.Printf("Jaccard: %.2f\n", jac) // 0.67
}

3. 字符串模糊搜索

func fuzzySearchExample() {
	strList := []string{"hello", "world", "golang", "good", "hallo", "hell"}
	target := "hello"

	// 查找最相似的字符串
	result, err := goedlib.FuzzySearch(target, strList, goedlib.Levenshtein)
	if err != nil {
		panic(err)
	}
	fmt.Printf("最相似的字符串: %s\n", result) // hello

	// 查找相似度大于阈值的所有字符串
	matches, err := goedlib.FuzzySearchThreshold(target, strList, 0.6, goedlib.JaroWinkler)
	if err != nil {
		panic(err)
	}
	fmt.Printf("相似度>0.6的字符串: %v\n", matches) // [hello hallo hell]
}

4. 字符串差异高亮

func diffHighlightExample() {
	str1 := "kitten"
	str2 := "sitting"

	diff := goedlib.Diff(str1, str2, goedlib.Levenshtein)
	fmt.Println("差异高亮:")
	fmt.Println(diff[0]) // k(i)t(t)e(n)
	fmt.Println(diff[1]) // s(i)t(t)i(n)g)
}

性能考虑

不同算法的性能特点:

  1. Levenshtein/Damerau-Levenshtein: 精确但较慢,O(n*m)时间复杂度
  2. Jaro-Winkler: 较快,适合短字符串
  3. Cosine/Jaccard: 适合基于词或n-gram的比较

对于大数据集,可以考虑先使用快速算法(如Jaro-Winkler)筛选,再对候选结果使用更精确的算法。

实际应用场景

  1. 拼写检查与纠正:
func suggestCorrection(input string, dictionary []string) string {
	result, _ := goedlib.FuzzySearch(input, dictionary, goedlib.JaroWinkler)
	return result
}
  1. 数据清洗:
func deduplicateSimilar(list []string, threshold float64) []string {
	var result []string
	for _, s1 := range list {
		found := false
		for _, s2 := range result {
			sim, _ := goedlib.StringSimilarity(s1, s2, goedlib.Levenshtein)
			if sim > threshold {
				found = true
				break
			}
		}
		if !found {
			result = append(result, s1)
		}
	}
	return result
}
  1. 搜索建议:
func getSearchSuggestions(query string, options []string) []string {
	var suggestions []string
	for _, opt := range options {
		sim, _ := goedlib.StringSimilarity(query, opt, goedlib.Cosine)
		if sim > 0.7 {
			suggestions = append(suggestions, opt)
		}
	}
	return suggestions
}

总结

go-edlib提供了丰富的字符串比较算法,可以满足从精确匹配到模糊搜索的各种需求。根据具体场景选择合适的算法:

  • 需要精确编辑距离时:Levenshtein/Damerau-Levenshtein
  • 快速模糊匹配:Jaro-Winkler
  • 基于词或n-gram的比较:Cosine/Jaccard
  • 短字符串比较:Hamming

通过合理使用这些算法,可以显著提升应用程序处理自然语言和用户输入的灵活性和用户体验。

回到顶部