我正在尝试通过可选地应用替换来生成字符串变体。
例如,一个替换方案是删除任何空白字符序列。 而不是替换所有出现的事件,如
>>> re.sub(r'\s+', '', 'a b c')
'abc'
- 相反,我需要为每次出现生成两个变体,因为替换是在一个变体中执行,而不是在另一个变体中执行。
对于字符串'a b c'
我想要变种
['a b c', 'a bc', 'ab c', 'abc']
即。所有二元决策的叉积(结果显然包括原始字符串)。
对于这种情况,可以使用re.finditer
和itertools.product
生成变体:
def vary(target, pattern, subst):
occurrences = [m.span() for m in pattern.finditer(target)]
for path in itertools.product((True, False), repeat=len(occurrences)):
variant = ''
anchor = 0
for (start, end), apply_this in zip(occurrences, path):
if apply_this:
variant += target[anchor:start] + subst
anchor = end
variant += target[anchor:]
yield variant
这为上面的例子产生了所需的输出:
>>> list(vary('a b c', re.compile(r'\s+'), ''))
['abc', 'ab c', 'a bc', 'a b c']
但是,此解决方案仅适用于固定字符串替换。
像re.sub
这样的群组参考的高级功能不能像这样做,
如下例所示,用于在单词内的一系列数字之后插入空格:
re.sub(r'\B(\d+)\B'), r'\1 ', 'abc123def')
如何扩展或更改方法以接受re.sub的任何有效参数 (没有编写用于解释组引用的解析器)?
答案 0 :(得分:1)
这个怎么样:
true
对于每个匹配,我们让re.sub()完成它的工作(在一次替换后计数为1),或者我们抢夺字符串中未更改的部分。
尝试使用这样的示例
def vary(target, pattern, subst):
numOccurences = len (pattern.findall (target))
for path in itertools.product((True, False), repeat=numOccurences):
variant = ''
remainingStr = target
for currentFlag in path:
if currentFlag:
remainingStr = pattern.sub (subst, remainingStr, 1)
else:
currentMatch = pattern.search (remainingStr);
variant += remainingStr[:currentMatch.end ()]
remainingStr = remainingStr[currentMatch.end ():]
variant += remainingStr
yield variant
我得到了
target = 'a b c'
pattern = re.compile(r'\s+')
subst = ''
print list (vary(target, pattern, subst))
target = 'abc123def'
pattern = re.compile(r'\B(\d+)\B')
subst = r'\1 '
print list (vary(target, pattern, subst))
答案 1 :(得分:1)
考虑让subst
成为可访问匹配数据的可调用对象,最终让我了解MatchObject.expand
。因此,作为近似值,subst
保留r
字符串,
def vary(target, pattern, subst):
matches = [m for m in pattern.finditer(target)]
occurrences = [m.span() for m in matches]
for path in itertools.product((True, False), repeat=len(occurrences)):
variant = ''
anchor = 0
for match, (start, end), apply_this in zip(matches, occurrences, path):
if apply_this:
variant += target[anchor:start] + match.expand(subst)
anchor = end
variant += target[anchor:]
yield variant
但是,我不确定这是否涵盖了引用主题字符串所需的所有灵活性,与相应的匹配相关。我想到了拆分字符串的索引功率集,但我想这距离提到的解析器不远。