chore: refactor (#2875)
This commit is contained in:
@@ -100,33 +100,6 @@ func (n *node) find(chars []rune) []scope {
|
|||||||
func (n *node) longestMatch(chars []rune, paths []*node) (uselessLen, matchLen int, nextPaths []*node) {
|
func (n *node) longestMatch(chars []rune, paths []*node) (uselessLen, matchLen int, nextPaths []*node) {
|
||||||
cur := n
|
cur := n
|
||||||
var longestMatched *node
|
var longestMatched *node
|
||||||
findMatch := func(path []*node) (*node, int) {
|
|
||||||
var (
|
|
||||||
result *node
|
|
||||||
start int
|
|
||||||
)
|
|
||||||
for i := len(path) - 1; i >= 0; i-- {
|
|
||||||
icur := path[i]
|
|
||||||
var cur *node
|
|
||||||
for icur.fail != nil {
|
|
||||||
if icur.fail.end {
|
|
||||||
cur = icur.fail
|
|
||||||
break
|
|
||||||
}
|
|
||||||
icur = icur.fail
|
|
||||||
}
|
|
||||||
if cur != nil {
|
|
||||||
if result == nil {
|
|
||||||
result = cur
|
|
||||||
start = i - result.depth + 1
|
|
||||||
} else if curStart := i - cur.depth + 1; curStart < start {
|
|
||||||
result = cur
|
|
||||||
start = curStart
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result, start
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := len(paths); i < len(chars); i++ {
|
for i := len(paths); i < len(chars); i++ {
|
||||||
char := chars[i]
|
char := chars[i]
|
||||||
@@ -141,21 +114,25 @@ func (n *node) longestMatch(chars []rune, paths []*node) (uselessLen, matchLen i
|
|||||||
if longestMatched != nil {
|
if longestMatched != nil {
|
||||||
return 0, longestMatched.depth, nil
|
return 0, longestMatched.depth, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.end {
|
if n.end {
|
||||||
return 0, n.depth, nil
|
return 0, n.depth, nil
|
||||||
}
|
}
|
||||||
// old path pre longest preMatch
|
|
||||||
preMatch, preStart := findMatch(paths)
|
|
||||||
// new path match
|
// new path match
|
||||||
var jump *node
|
var jump *node
|
||||||
|
// old path pre longest preMatch
|
||||||
|
preMatch, preStart := findMatch(paths)
|
||||||
icur := cur
|
icur := cur
|
||||||
for icur.fail != nil {
|
for icur.fail != nil {
|
||||||
jump, ok = icur.fail.children[char]
|
jump, ok = icur.fail.children[char]
|
||||||
if ok {
|
if ok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
icur = icur.fail
|
icur = icur.fail
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case preMatch != nil && jump != nil:
|
case preMatch != nil && jump != nil:
|
||||||
if jumpStart := i - jump.depth + 1; preStart < jumpStart {
|
if jumpStart := i - jump.depth + 1; preStart < jumpStart {
|
||||||
@@ -172,16 +149,48 @@ func (n *node) longestMatch(chars []rune, paths []*node) (uselessLen, matchLen i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// this longest matched node
|
// this longest matched node
|
||||||
if longestMatched != nil {
|
if longestMatched != nil {
|
||||||
return 0, longestMatched.depth, nil
|
return 0, longestMatched.depth, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.end {
|
if n.end {
|
||||||
return 0, n.depth, nil
|
return 0, n.depth, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
match, start := findMatch(paths)
|
match, start := findMatch(paths)
|
||||||
if match != nil {
|
if match != nil {
|
||||||
return start, match.depth, nil
|
return start, match.depth, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return len(chars), 0, nil
|
return len(chars), 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func findMatch(path []*node) (*node, int) {
|
||||||
|
var result *node
|
||||||
|
var start int
|
||||||
|
|
||||||
|
for i := len(path) - 1; i >= 0; i-- {
|
||||||
|
icur := path[i]
|
||||||
|
var cur *node
|
||||||
|
for icur.fail != nil {
|
||||||
|
if icur.fail.end {
|
||||||
|
cur = icur.fail
|
||||||
|
break
|
||||||
|
}
|
||||||
|
icur = icur.fail
|
||||||
|
}
|
||||||
|
if cur != nil {
|
||||||
|
if result == nil {
|
||||||
|
result = cur
|
||||||
|
start = i - result.depth + 1
|
||||||
|
} else if curStart := i - cur.depth + 1; curStart < start {
|
||||||
|
result = cur
|
||||||
|
start = curStart
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, start
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,9 +33,10 @@ func NewReplacer(mapping map[string]string) Replacer {
|
|||||||
// Replace replaces text with given substitutes.
|
// Replace replaces text with given substitutes.
|
||||||
func (r *replacer) Replace(text string) string {
|
func (r *replacer) Replace(text string) string {
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
|
var paths []*node
|
||||||
target := []rune(text)
|
target := []rune(text)
|
||||||
cur := r.node
|
cur := r.node
|
||||||
var paths []*node
|
|
||||||
for len(target) != 0 {
|
for len(target) != 0 {
|
||||||
uselessLen, matchLen, nextPaths := cur.longestMatch(target, paths)
|
uselessLen, matchLen, nextPaths := cur.longestMatch(target, paths)
|
||||||
if uselessLen > 0 {
|
if uselessLen > 0 {
|
||||||
@@ -54,5 +55,6 @@ func (r *replacer) Replace(text string) string {
|
|||||||
paths = nil
|
paths = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -211,3 +211,11 @@ func TestFuzzReplacerCase2(t *testing.T) {
|
|||||||
t.Errorf("result: %s, match: %v", val, keys)
|
t.Errorf("result: %s, match: %v", val, keys)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReplacer_ReplaceLongestMatch(t *testing.T) {
|
||||||
|
replacer := NewReplacer(map[string]string{
|
||||||
|
"日本的首都": "东京",
|
||||||
|
"日本": "本日",
|
||||||
|
})
|
||||||
|
assert.Equal(t, "东京是东京", replacer.Replace("日本的首都是东京"))
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user