62 lines
1.2 KiB
Go
62 lines
1.2 KiB
Go
|
package main
|
||
|
|
||
|
import "math"
|
||
|
|
||
|
func Jaro(a, b string) float64 {
|
||
|
la := float64(len(a))
|
||
|
lb := float64(len(b))
|
||
|
|
||
|
// match range = max(len(a), len(b)) / 2 - 1
|
||
|
matchRange := int(math.Floor(math.Max(la, lb)/2.0)) - 1
|
||
|
matchRange = int(math.Max(0, float64(matchRange-1)))
|
||
|
var matches, halfs float64
|
||
|
transposed := make([]bool, len(b))
|
||
|
|
||
|
for i := 0; i < len(a); i++ {
|
||
|
start := int(math.Max(0, float64(i-matchRange)))
|
||
|
end := int(math.Min(lb-1, float64(i+matchRange)))
|
||
|
|
||
|
for j := start; j <= end; j++ {
|
||
|
if transposed[j] {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
if a[i] == b[j] {
|
||
|
if i != j {
|
||
|
halfs++
|
||
|
}
|
||
|
matches++
|
||
|
transposed[j] = true
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if matches == 0 {
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
transposes := math.Floor(float64(halfs / 2))
|
||
|
|
||
|
return ((matches / la) + (matches / lb) + (matches-transposes)/matches) / 3.0
|
||
|
}
|
||
|
|
||
|
|
||
|
func JaroWinkler(a, b string, boostThreshold float64, prefixSize int) float64 {
|
||
|
j := Jaro(a, b)
|
||
|
|
||
|
if j <= boostThreshold {
|
||
|
return j
|
||
|
}
|
||
|
|
||
|
prefixSize = int(math.Min(float64(len(a)), math.Min(float64(prefixSize), float64(len(b)))))
|
||
|
|
||
|
var prefixMatch float64
|
||
|
for i := 0; i < prefixSize; i++ {
|
||
|
if a[i] == b[i] {
|
||
|
prefixMatch++
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return j + 0.1*prefixMatch*(1.0-j)
|
||
|
}
|