Initial QSfera import
This commit is contained in:
+140
@@ -0,0 +1,140 @@
|
||||
package strutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gookit/goutil/mathutil"
|
||||
)
|
||||
|
||||
// SimilarComparator definition
|
||||
//
|
||||
// links:
|
||||
//
|
||||
// https://github.com/mkideal/cli/blob/master/fuzzy.go
|
||||
type SimilarComparator struct {
|
||||
src, dst string
|
||||
}
|
||||
|
||||
// NewComparator create
|
||||
func NewComparator(src, dst string) *SimilarComparator {
|
||||
return &SimilarComparator{src, dst}
|
||||
}
|
||||
|
||||
// Similarity calc for two string.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// rate, ok := Similarity("hello", "he")
|
||||
func Similarity(s, t string, rate float32) (float32, bool) {
|
||||
return NewComparator(s, t).Similar(rate)
|
||||
}
|
||||
|
||||
// Similar by minDifferRate
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// c := NewComparator("hello", "he")
|
||||
// rate, ok :c.Similar(0.3)
|
||||
func (c *SimilarComparator) Similar(minDifferRate float32) (float32, bool) {
|
||||
dist := c.editDistance([]byte(c.src), []byte(c.dst))
|
||||
differRate := dist / float32(mathutil.Max(len(c.src), len(c.dst))+4)
|
||||
|
||||
return differRate, differRate >= minDifferRate
|
||||
}
|
||||
|
||||
func (c *SimilarComparator) editDistance(s, t []byte) float32 {
|
||||
var (
|
||||
m = len(s)
|
||||
n = len(t)
|
||||
d = make([][]float32, m+1)
|
||||
)
|
||||
for i := 0; i < m+1; i++ {
|
||||
d[i] = make([]float32, n+1)
|
||||
d[i][0] = float32(i)
|
||||
}
|
||||
for j := 0; j < n+1; j++ {
|
||||
d[0][j] = float32(j)
|
||||
}
|
||||
|
||||
for j := 1; j < n+1; j++ {
|
||||
for i := 1; i < m+1; i++ {
|
||||
if s[i-1] == t[j-1] {
|
||||
d[i][j] = d[i-1][j-1]
|
||||
} else {
|
||||
d[i][j] = mathutil.Min(d[i-1][j]+1, mathutil.Min(d[i][j-1]+1, d[i-1][j-1]+1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return d[m][n]
|
||||
}
|
||||
|
||||
// Builder struct
|
||||
type Builder struct {
|
||||
strings.Builder
|
||||
}
|
||||
|
||||
// Write bytes and no error report
|
||||
func (b *Builder) Write(p []byte) {
|
||||
_, _ = b.Builder.Write(p)
|
||||
}
|
||||
|
||||
// WriteRune and no error report
|
||||
func (b *Builder) WriteRune(r rune) {
|
||||
_, _ = b.Builder.WriteRune(r)
|
||||
}
|
||||
|
||||
// WriteByteNE write byte and no error report
|
||||
func (b *Builder) WriteByteNE(c byte) {
|
||||
_ = b.WriteByte(c)
|
||||
}
|
||||
|
||||
// WriteString to builder
|
||||
func (b *Builder) WriteString(s string) {
|
||||
_, _ = b.Builder.WriteString(s)
|
||||
}
|
||||
|
||||
// Writef write string by fmt.Sprintf formatted
|
||||
func (b *Builder) Writef(tpl string, vs ...any) {
|
||||
_, _ = b.Builder.WriteString(fmt.Sprintf(tpl, vs...))
|
||||
}
|
||||
|
||||
// Writeln write string with newline.
|
||||
func (b *Builder) Writeln(s string) {
|
||||
_, _ = b.Builder.WriteString(s)
|
||||
_ = b.WriteByte('\n')
|
||||
}
|
||||
|
||||
// WriteAny write any type value.
|
||||
func (b *Builder) WriteAny(v any) {
|
||||
_, _ = b.Builder.WriteString(QuietString(v))
|
||||
}
|
||||
|
||||
// WriteAnys write any type values.
|
||||
func (b *Builder) WriteAnys(vs ...any) {
|
||||
for _, v := range vs {
|
||||
_, _ = b.Builder.WriteString(QuietString(v))
|
||||
}
|
||||
}
|
||||
|
||||
// WriteMulti write multi byte at once.
|
||||
func (b *Builder) WriteMulti(bs ...byte) {
|
||||
for _, b2 := range bs {
|
||||
_ = b.WriteByte(b2)
|
||||
}
|
||||
}
|
||||
|
||||
// WriteStrings write multi string at once.
|
||||
func (b *Builder) WriteStrings(ss ...string) {
|
||||
for _, s := range ss {
|
||||
_, _ = b.Builder.WriteString(s)
|
||||
}
|
||||
}
|
||||
|
||||
// ResetGet return current string and reset builder
|
||||
func (b *Builder) ResetGet() string {
|
||||
s := b.String()
|
||||
b.Reset()
|
||||
return s
|
||||
}
|
||||
Reference in New Issue
Block a user