字符串正则表达式两个不匹配项 Python
String regex two mismatches Python
我如何扩展下面的代码以允许我探索我的子字符串和父字符串之间有 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']
显然,在上面的代码中包含两个不匹配的可能性需要对所有可能的组合进行大量的暴力输入。
我如何扩展此代码(或重构此代码)以探索两个不匹配的可能性?
此外,我想修改我的输出,以便获得子字符串与字符串匹配的确切位置的返回数字索引(不是 SSQQ
或 SSQP
)。
组合爆炸并不是 四个中的两个不匹配的坏处。
首先,请注意您可以省略 SSQP
本身,因为它包含在所有更宽松的案例中。
re.findall(r'(?=([A-Z]SQP|S[A-Z]QP|SS[A-Z]P|SSQ[A-Z]))', s)
所以,案例数是
4!
C(4, 1) = ––––––––––––– = 4
1! * (4 - 1)!
对于最多两个不匹配的情况,案例数是
4!
C(4, 2) = ––––––––––––– = 6
2! * (4 - 2)!
即
re.findall('(?=(SS..|S.Q.|S..P|.SQ.|.S.P|..QP))', s)
(为了简化说明,我冒昧地写了 .
而不是 [A-Z]
。)
要获取匹配项的位置而不是匹配项的文本:
[match.start(0) for match in re.finditer('(?=(SS..|S.Q.|S..P|.SQ.|.S.P|..QP))', s)]
你不必在这里使用 re
你可以使用 itertools
模块来代替并节省大量内存。
您可以先提取所有长度为 4 的子字符串,然后将它们与您的 substring
进行比较,然后仅 select 那些与您的 substring
相差小于 2 的子字符串:
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))
演示:
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']
如果你想要 return 索引,你需要将索引放在 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]
演示:
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]
我如何扩展下面的代码以允许我探索我的子字符串和父字符串之间有 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']
显然,在上面的代码中包含两个不匹配的可能性需要对所有可能的组合进行大量的暴力输入。
我如何扩展此代码(或重构此代码)以探索两个不匹配的可能性?
此外,我想修改我的输出,以便获得子字符串与字符串匹配的确切位置的返回数字索引(不是 SSQQ
或 SSQP
)。
组合爆炸并不是 四个中的两个不匹配的坏处。
首先,请注意您可以省略 SSQP
本身,因为它包含在所有更宽松的案例中。
re.findall(r'(?=([A-Z]SQP|S[A-Z]QP|SS[A-Z]P|SSQ[A-Z]))', s)
所以,案例数是
4!
C(4, 1) = ––––––––––––– = 4
1! * (4 - 1)!
对于最多两个不匹配的情况,案例数是
4!
C(4, 2) = ––––––––––––– = 6
2! * (4 - 2)!
即
re.findall('(?=(SS..|S.Q.|S..P|.SQ.|.S.P|..QP))', s)
(为了简化说明,我冒昧地写了 .
而不是 [A-Z]
。)
要获取匹配项的位置而不是匹配项的文本:
[match.start(0) for match in re.finditer('(?=(SS..|S.Q.|S..P|.SQ.|.S.P|..QP))', s)]
你不必在这里使用 re
你可以使用 itertools
模块来代替并节省大量内存。
您可以先提取所有长度为 4 的子字符串,然后将它们与您的 substring
进行比较,然后仅 select 那些与您的 substring
相差小于 2 的子字符串:
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))
演示:
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']
如果你想要 return 索引,你需要将索引放在 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]
演示:
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]