我正在为我的问题寻找更多的pythonic或函数式编程解决方案。
我将regular expression
与字符串匹配。正则表达式捕获每个重复的通配符周围的组。我使用这些组来掩盖匹配中的通配符。以下代码中显示了一个示例:
out_str_list = []
original_str = 'XYZQUACKESTARNFSDMADESBHSCHILDABCD'
match = re.search('(?=(QUACK(.{2,4})TAR(.{2,4})MAD(.{3,5})CHILD))', original_str) # searching while grouping repetitions of wildcards
hide_ranges = tuple(match.span(i) for i in range(2, len(match.groups()) + 1)) # ((8, 10), (13, 17), (20, 25))
match_range = match.span(1) # (3, 30)
i = 0
out_str_list.append(original_str[match.span(1)[0]:hide_ranges[0][0]])
while i < len(hide_ranges):
out_str_list.append("-({0})-".format(hide_ranges[i][1] - hide_ranges[i][0]))
if i == 0 and len(hide_ranges) != 1:
out_str_list.append(original_str[hide_ranges[0][1]:hide_ranges[1][0]])
elif i == len(hide_ranges) - 1:
pass
else:
out_str_list.append(original_str[hide_ranges[i][1]:hide_ranges[i+1][0]])
i += 1
out_str_list.append(original_str[hide_ranges[i-1][1]:match.span(1)[1]])
match_str = ''.join(out_str_list)
assert match_str = 'QUACK-(2)-TAR-(4)-MAD-(5)-CHILD'
代码有效,但似乎比需要的更冗长。此示例的更一般形式:
我有一个字符串:XYZQUACKESTARNFSDMADESBHSCHILDABCD
从正则表达式匹配中,我生成元组:((8, 10), (13, 17), (20, 25))
以及包含匹配的起始和结束索引的元组:(3, 30)
如何获得如下字符串:QUACK-(2)-TAR-(4)-MAD-(5)-CHILD
?
我想为每个捕获的组执行类似str.split
和str.join({length of gap})
的操作。我无法做到这一点,因为我给了索引而不是字符串来分割。我知道函数式编程方法会使用map或filter之类的东西,但我不确定如何以我想要的方式应用字符串切片。
答案 0 :(得分:4)
您可以使用re.split
提取字符串的不匹配部分,并使用re.findall
查找字符串的匹配部分。然后,您可以遍历这些集合,并将数据聚合在一起:
import re
s = 'XYZQUACKESTARNFSDMADESBHSCHILDABCD'
matches = re.findall('QUACK|TAR|MAD|CHILD',s)
non_matches = re.split('QUACK|TAR|MAD|CHILD',s)
'-'.join(["{}-({})".format(matches[i], len(non_matches[i+1])) for i in range(len(matches))])
#'QUACK-(2)-TAR-(4)-MAD-(5)-CHILD-(4)'
答案 1 :(得分:1)
回想一下re.sub
可以使用替换功能,所以你可以这样做:
>>> s='XYZQUACKESTARNFSDMADESBHSCHILDABCD'
>>> def mh(m):
... return "{}-({})-{}-({})-{}-({})-{}".format(m.group(1),len(m.group(2)),m.group(3),len(m.group(4)),m.group(5),len(m.group(6)),m.group(7))
...
>>> re.sub(r'^.*(QUACK)(.{2,4})(TAR)(.{2,4})(MAD)(.{3,5})(CHILD).*$', mh, s)
'QUACK-(2)-TAR-(4)-MAD-(5)-CHILD'
你也可以使用你的正则表达式替换Python的字符串:
>>> m=re.search(r'(?=(QUACK(.{2,4})TAR(.{2,4})MAD(.{3,5})CHILD))', s)
>>> tgt=m.groups()[0]
>>> for r1, r2 in [(e, '-({})-'.format(len(e))) for e in m.groups()[1:]]:
... tgt=tgt.replace(r1, r2, 1)
...
>>> tgt
'QUACK-(2)-TAR-(4)-MAD-(5)-CHILD'