Заменить все слово без использования регулярных выражений - PullRequest
0 голосов
/ 28 февраля 2020

Я использую string.Replace для замены подстроки A

func removeIP(text string) string {
    text = strings.Replace(text, "someWord", "**NewWord**", -1)
    return text
}

func removeIPUsingRegex(text string) string {
    var re = regexp.MustCompile(`\b` + "someWord" + `\b`) // I want to replace whole word only
    text = re.ReplaceAllString(text, "**NewWord**")
}

Проблема, с которой я здесь сталкиваюсь, заключается в том, что я хочу заменить целое слово, только если не поддерживается замена строки.
Поскольку я должен заменить очень очень большие строки могут быть в ГБ. Regex очень медленный по сравнению со строкой replace.
например: text: "abcdef defgh /def/ .def/ =def= def xxxy" -> Replace def с DEF
output: "abcdef defgh /DEF/ .DEF/ =DEF= DEF xxxy" // Обратите внимание, что были заменены только целые слова.

Regex увеличивает время почти в 100 раз (https://medium.com/codezillas/golang-replace-vs-regexp-de4e48482f53). Любые идеи будут высоко оценены.

1 Ответ

0 голосов
/ 29 февраля 2020

KMP ALGorithm используется
// ReplaceWholeWord ...

 func ReplaceWholeWord(text string, oldWord string, newWord string) string {
        var patternLength = len(oldWord)
        var textLength = len(text) 

        var copyIndex = 0
        var textIndex = 0
        var patternIndex = 0
        var newString strings.Builder
        var lps = computeLPSArray(oldWord)

        for textIndex < textLength {
            if oldWord[patternIndex] == text[textIndex] {
                patternIndex++
                textIndex++
            }
            if patternIndex == patternLength {
                startIndex := textIndex - patternIndex
                endIndex := textIndex - patternIndex + patternLength - 1

                if checkIfWholeWord(text, startIndex, endIndex) {
                    if copyIndex != startIndex {
                        newString.WriteString(text[copyIndex:startIndex])
                    }
                    newString.WriteString(newWord)
                    copyIndex = endIndex + 1
                }

                patternIndex = 0
                textIndex = endIndex + 1

            } else if textIndex < textLength && oldWord[patternIndex] != text[textIndex] {

                if patternIndex != 0 {
                    patternIndex = lps[patternIndex-1]

                } else {
                    textIndex = textIndex + 1
                }

            }
        }
        newString.WriteString(text[copyIndex:])

        return newString.String()
    }

    func computeLPSArray(pattern string) []int {
        var length = 0
        var i = 1
        var patternLength = len(pattern)

        var lps = make([]int, patternLength)

        lps[0] = 0

        for i = 1; i < patternLength; {
            if pattern[i] == pattern[length] {
                length++
                lps[i] = length
                i++

            } else {

                if length != 0 {
                    length = lps[length-1]

                } else {
                    lps[i] = length
                    i++
                }
            }
        }
        return lps
    }

    func checkIfWholeWord(text string, startIndex int, endIndex int) bool {
        startIndex = startIndex - 1
        endIndex = endIndex + 1

        if (startIndex < 0 && endIndex >= len(text)) ||
            (startIndex < 0 && endIndex < len(text) && isNonWord(text[endIndex])) ||
            (startIndex >= 0 && endIndex >= len(text) && isNonWord(text[startIndex])) ||
            (startIndex >= 0 && endIndex < len(text) && isNonWord(text[startIndex]) && isNonWord(text[endIndex])) {
            return true
        }

        return false
    }

    func isNonWord(c byte) bool {
        return !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_'))
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...