快速搜索给定字符串的开始位置

时间:2019-07-18 19:13:38

标签: python levenshtein-distance

在这里,我想将给定的字符串match_text与更长的字符串text匹配。我想在match_text中找到text的起始位置,最接近的位置(可以假设只有一个位置)。我当前的代码版本是for遍历text范围并计算Levenshtein距离。但是,有时文本确实很长(最多90k个字符)。我不确定是否有快速的方法来进行字符串搜索。这是我编写的代码段的当前版本:

import numpy as np
import Levenshtein as lev # pip install python-Levenshtein

def find_start_position(text, match_text):
    lev_distances = []
    for i in range(len(text) - len(match_text)):
        match_len = len(match_text)
        lev_distances.append(lev.distance(match_text, text[i: i + match_len]))
    pos = np.argmin(lev_distances)
    return pos

# example
find_start_position('I think this is really cool.', 'this iz')
>> 8

如果有人知道或进行了快速的字符串搜索,我将不胜感激。

1 个答案:

答案 0 :(得分:1)

  

请注意:模式中的空白已标准化。这是你吗   在寻找吗?

import Levenshtein as lev # pip install python-Levenshtein
import sys
# author hry@solaris-it.com

def splitTextInWords(text):
    retVal = text.split() 
    return retVal

def getBestFit(allLevenshteinValues):
    bestFit = [sys.maxsize, '', 0]
    for k, value in allLevenshteinValues.items():
        if value[0] < bestFit[0]:
            bestFit = value
            bestFit.append(k + 1)       
    return bestFit

def catchAllCosts(text, matchText):
    textAsWordList   = splitTextInWords(text)
    matchTextPattern = ' '.join(splitTextInWords(matchText))
    maxIndx = len(textAsWordList)
    allLevenshteinValues = {}
    for i in range(0, maxIndx):
        extCnt = 0
        textPattern = textAsWordList[i]
        while (len(textPattern) < len(matchTextPattern) 
        and i + extCnt + 1 < maxIndx):
            if i + extCnt + 1  < maxIndx:
                extCnt += 1
            textPattern = ' '.join([textPattern, textAsWordList[i + extCnt]])
        allLevenshteinValues[i] = [ lev.distance(
        textPattern, matchTextPattern), textPattern ]
    return allLevenshteinValues

def main():
    # text: pattern you are crowling
    text = '''x AlongLongLongWord and long long long long string 
    is going be  here string I think    really S is cXXXl. 
    x AlongLongLongWord 今x  Go今天今 I think really this would is cxol.x 
    AlongLongLongWord I think this izreally this iz cool.''' 
    # matchText: pattern you want find the best match for
    matchText = 'this is'

    allLevenshteinValues = catchAllCosts(text, matchText)
    bestFit =  getBestFit(allLevenshteinValues)
    costs, sequence, wordNr,   = bestFit[0], bestFit[1], bestFit[2]
    print("first best match starting by word nr.",
          wordNr, "costs:", costs, "sequence: >>", sequence, "<<")

    matchAnotherPattern = '今天  Go今x天今'
    allLevenshteinValues = catchAllCosts(text, matchAnotherPattern)
    bestFit =  getBestFit(allLevenshteinValues)
    costs, sequence, wordNr,   = bestFit[0], bestFit[1], bestFit[2]
    print("first best match starting by word nr.",
          wordNr, "costs:", costs, "sequence: >>", sequence, "<<")


if __name__ == '__main__':
    main()