parent
6383ebbf48
commit
cf8f88dd5d
@ -0,0 +1,3 @@ |
||||
package simplify |
||||
|
||||
//TODO 如果是层级筛选,有 父级code 就不再需要 子级code 了
|
@ -0,0 +1,172 @@ |
||||
package simplify |
||||
|
||||
import ( |
||||
"slices" |
||||
"strings" |
||||
"unicode" |
||||
) |
||||
|
||||
// 模拟ES部分分词规则,对查询关键字进行去重
|
||||
|
||||
type Words struct { |
||||
whole []string |
||||
input []string |
||||
} |
||||
|
||||
func NewWords(whole []string, input []string) *Words { |
||||
return &Words{whole: whole, input: input} |
||||
} |
||||
|
||||
func (w *Words) Simplify() []string { |
||||
|
||||
// 分隔符列表,与ES搜索的分隔符保持一致
|
||||
separators := w.separators() |
||||
|
||||
keywords := make([]string, 0) |
||||
keywords = append(keywords, w.input...) |
||||
keywords = append(keywords, w.whole...) |
||||
|
||||
wides := make(map[string]string) |
||||
for _, keyword := range keywords { |
||||
// 转换为小写并去除两端空白字符,规避大小写造成异常剔除
|
||||
keyword = strings.ToLower(strings.TrimSpace(keyword)) |
||||
if keyword == "" { |
||||
continue |
||||
} |
||||
// 将分隔符替换为空格
|
||||
str := keyword |
||||
for _, separator := range separators { |
||||
str = strings.ReplaceAll(str, separator, " ") |
||||
} |
||||
wide := " " + strings.Join(strings.Fields(str), " ") + " " // 空格开头结尾,便于包含判断
|
||||
if strings.TrimSpace(wide) == "" { |
||||
continue |
||||
} |
||||
wides[keyword] = wide |
||||
} |
||||
|
||||
// 计算重复次数
|
||||
repetition := make(map[string]int) |
||||
for _, wide1 := range wides { |
||||
for keyword, wide2 := range wides { |
||||
|
||||
// 首尾空格字符串 包含另一个 首尾空格字符串,则认为重复
|
||||
if strings.Contains(wide2, wide1) { |
||||
repetition[keyword]++ |
||||
continue |
||||
} |
||||
|
||||
// 子串 在 首尾空格父串 中, 前后位置的字符 是 中文或空格,也认为重复
|
||||
before, after := w.checkSurroundingChineseOrSpace([]rune(wide2), []rune(strings.TrimSpace(wide1))) |
||||
if before && after { |
||||
repetition[keyword]++ |
||||
continue |
||||
} |
||||
} |
||||
} |
||||
|
||||
// 筛选出不重复且不是输入的字符串
|
||||
filteredInput := make([]string, 0) |
||||
filteredWhole := make([]string, 0) |
||||
for keyword, times := range repetition { |
||||
if times == 1 { |
||||
if slices.Contains(w.input, keyword) { |
||||
filteredInput = append(filteredInput, keyword) |
||||
} else { |
||||
filteredWhole = append(filteredWhole, keyword) |
||||
} |
||||
} |
||||
} |
||||
|
||||
result := make([]string, 0) |
||||
result = append(result, filteredInput...) // ‘input’ 放在前面,保证输入字符串优先
|
||||
result = append(result, filteredWhole...) |
||||
return result |
||||
} |
||||
|
||||
// isChineseOrSpace 判断给定的rune字符是否为中文或空格
|
||||
func (w *Words) isChineseOrSpace(r rune) bool { |
||||
return r == ' ' || unicode.Is(unicode.Scripts["Han"], r) |
||||
} |
||||
|
||||
// CheckSurroundingChineseOrSpace 检查子串sub前后的UTF-8字符是否为中文或空格
|
||||
func (w *Words) checkSurroundingChineseOrSpace(str []rune, sub []rune) (bool, bool) { |
||||
// 找到子串在父串中的位置
|
||||
startIndex := -1 |
||||
lenStr := len(str) |
||||
lenSub := len(sub) |
||||
for i := 0; i <= lenStr-lenSub; i++ { |
||||
if str[i] == sub[0] { // 找到子串的起始字符
|
||||
match := true |
||||
for j := 1; j < lenSub; j++ { |
||||
if i+j >= lenStr || str[i+j] != sub[j] { |
||||
match = false |
||||
break |
||||
} |
||||
} |
||||
if match { |
||||
startIndex = i |
||||
break |
||||
} |
||||
} |
||||
} |
||||
|
||||
if startIndex == -1 { |
||||
// 子串不在父串中
|
||||
return false, false |
||||
} |
||||
|
||||
// 检查子串前后的字符是否为中文或空格
|
||||
var isBeforeChineseOrSpace, isAfterChineseOrSpace bool |
||||
if startIndex > 0 { |
||||
isBeforeChineseOrSpace = w.isChineseOrSpace(str[startIndex-1]) |
||||
} |
||||
if startIndex+len(sub) < len(str) { |
||||
isAfterChineseOrSpace = w.isChineseOrSpace(str[startIndex+len(sub)]) |
||||
} |
||||
|
||||
return isBeforeChineseOrSpace, isAfterChineseOrSpace |
||||
} |
||||
|
||||
func (w *Words) separators() []string { |
||||
// 分隔符列表,与ES搜索的分隔符保持一致
|
||||
return []string{ |
||||
"~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", |
||||
// "_",
|
||||
"+", |
||||
|
||||
"`", "-", "=", |
||||
"{", "}", "|", |
||||
"[", "]", "\\", |
||||
|
||||
// ":",
|
||||
"\"", |
||||
|
||||
";", |
||||
// "'",
|
||||
|
||||
"<", ">", "?", |
||||
|
||||
",", |
||||
// ".",
|
||||
"/", |
||||
|
||||
"\r\n", "\r", "\n", "\t", |
||||
|
||||
"!", "¥", "…", "(", ")", "—", |
||||
|
||||
// "·",
|
||||
|
||||
"【", "】", "、", |
||||
|
||||
";", |
||||
// "‘",
|
||||
// "’",
|
||||
|
||||
// ":",
|
||||
"“", |
||||
|
||||
"》", "《", "?", |
||||
",", "。", "、", |
||||
} |
||||
} |
Loading…
Reference in new issue