فهرست منبع

chore: refactor (#2875)

Kevin Wan 2 سال پیش
والد
کامیت
072db116c3
3فایلهای تغییر یافته به همراه49 افزوده شده و 30 حذف شده
  1. 38 29
      core/stringx/node.go
  2. 3 1
      core/stringx/replacer.go
  3. 8 0
      core/stringx/replacer_test.go

+ 38 - 29
core/stringx/node.go

@@ -100,33 +100,6 @@ func (n *node) find(chars []rune) []scope {
 func (n *node) longestMatch(chars []rune, paths []*node) (uselessLen, matchLen int, nextPaths []*node) {
 	cur := n
 	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++ {
 		char := chars[i]
@@ -141,21 +114,25 @@ func (n *node) longestMatch(chars []rune, paths []*node) (uselessLen, matchLen i
 			if longestMatched != nil {
 				return 0, longestMatched.depth, nil
 			}
+
 			if n.end {
 				return 0, n.depth, nil
 			}
-			// old path pre longest preMatch
-			preMatch, preStart := findMatch(paths)
+
 			// new path match
 			var jump *node
+			// old path pre longest preMatch
+			preMatch, preStart := findMatch(paths)
 			icur := cur
 			for icur.fail != nil {
 				jump, ok = icur.fail.children[char]
 				if ok {
 					break
 				}
+
 				icur = icur.fail
 			}
+
 			switch {
 			case preMatch != nil && jump != nil:
 				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
 	if longestMatched != nil {
 		return 0, longestMatched.depth, nil
 	}
+
 	if n.end {
 		return 0, n.depth, nil
 	}
+
 	match, start := findMatch(paths)
 	if match != nil {
 		return start, match.depth, 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
+}

+ 3 - 1
core/stringx/replacer.go

@@ -33,9 +33,10 @@ func NewReplacer(mapping map[string]string) Replacer {
 // Replace replaces text with given substitutes.
 func (r *replacer) Replace(text string) string {
 	var buf strings.Builder
+	var paths []*node
 	target := []rune(text)
 	cur := r.node
-	var paths []*node
+
 	for len(target) != 0 {
 		uselessLen, matchLen, nextPaths := cur.longestMatch(target, paths)
 		if uselessLen > 0 {
@@ -54,5 +55,6 @@ func (r *replacer) Replace(text string) string {
 			paths = nil
 		}
 	}
+
 	return buf.String()
 }

+ 8 - 0
core/stringx/replacer_test.go

@@ -211,3 +211,11 @@ func TestFuzzReplacerCase2(t *testing.T) {
 		t.Errorf("result: %s, match: %v", val, keys)
 	}
 }
+
+func TestReplacer_ReplaceLongestMatch(t *testing.T) {
+	replacer := NewReplacer(map[string]string{
+		"日本的首都": "东京",
+		"日本":    "本日",
+	})
+	assert.Equal(t, "东京是东京", replacer.Replace("日本的首都是东京"))
+}