字符串正则表达式两个不匹配的Python

war*_*hip 5 python regex string-matching

如何扩展下面的代码以允许我探索我的子字符串和父字符串之间有2个不匹配或更少的所有实例?

子: SSQP

字符串到比赛到: SSPQQQQPSSSSQQQSSQPSPSQSSQPSSQPPSSSSQPSPSQSSQPSSSSQPSPSQSSQPSSSSQPSPSQ

以下是仅包含一个可能不匹配的示例:

>>> s = 'SSPQQQQPSSSSQQQSSQPSPSQSSQPSSQPPSSSSQPSPSQSSQPSSSSQPSPSQSSQPSSSSQPSPSQ'
>>> re.findall(r'(?=(SSQP|[A-Z]SQP|S[A-Z]QP|SS[A-Z]P|SSQ[A-Z]))', s)
['SSQQ', 'SSQP', 'SSQP', 'SSQP', 'SSQP', 'SSQP', 'SSQP', 'SSQP', 'SSQP']
Run Code Online (Sandbox Code Playgroud)

显然,在上面的代码中加入两个不匹配的可能性需要对所有可能的组合进行大量的暴力分类.

如何扩展此代码(或重构此代码)以探索两个不匹配的可能性?

此外,我想修改我的输出,以便我得到子字符串与字符串匹配的确切位置返回的数字索引(不是SSQQSSQP).

Kas*_*mvd 5

你不必re在这里使用你可以使用itertools模块代替并节省大量内存.

您可以先提取长度为4的所有子字符串,然后将它们与您进行比较,substring并选择与您的差别小于2的那些子字符串substring:

from itertools import izip,islice,tee

def sub_findre(s,substring,diffnumber):
    sublen=len(substring)
    zip_gen=(izip(substring,islice(s,i,i+sublen)) for i in xrange(len(s)))
    for z in zip_gen:
        l,z=tee(z)
        if sum(1 for i,j in l if i==j)>=sublen-diffnumber:
            new=izip(*z)
            next(new)
            yield ''.join(next(new))
Run Code Online (Sandbox Code Playgroud)

演示:

s='SSPQQQQPSSSSQQQSSQPSPSQSSQPSSQPPSSSSQPSPSQSSQPSSSSQPSPSQSSQPSSSSQPSPSQ'

substring='SSQP'
print list(sub_findre(s,substring,2))

['SSPQ', 'SPQQ', 'QQQP', 'SSSS', 'SSSQ', 'SSQQ', 'SQQQ', 'SSQP', 'PSQS', 'SSQP', 'SSQP', 'SQPP', 'SSSS', 'SSSQ', 'SSQP', 'PSQS', 'SSQP', 'SSSS', 'SSSQ', 'SSQP', 'PSQS', 'SSQP', 'SSSS', 'SSSQ', 'SSQP', 'PSQ']
Run Code Online (Sandbox Code Playgroud)

如果要返回索引,则需要将索引放在izip可用于itertools.repeat()重复索引的索引中,其长度为substring:

from itertools import izip,islice,tee,repeat

def sub_findre(s,substring,diffnumber):
    sublen=len(substring)
    zip_gen=(izip(substring,islice(s,i,i+sublen),repeat(i,sublen)) for i in xrange(len(s)))
    for z in zip_gen:
        l,z=tee(z)
        if sum(1 for i,j,_ in l if i==j)>=sublen-diffnumber:
            new=izip(*z)
            next(new)
            next(new)
            yield next(new)[0]
Run Code Online (Sandbox Code Playgroud)

演示:

print list(sub_findre(s,substring,2))
[0, 1, 4, 8, 9, 10, 11, 15, 20, 23, 27, 28, 32, 33, 34, 39, 42, 46, 47, 48, 53, 56, 60, 61, 62, 67]
Run Code Online (Sandbox Code Playgroud)