6

オプションで置換を適用して文字列バリアントを作成しようとしています。

たとえば、1 つの置換方式では、一連の空白文字を削除します。のようにすべてのオカレンスを置き換えるのではなく、

>>> re.sub(r'\s+', '', 'a b c')
'abc'

– 代わりに、オカレンスごとに 2 つのバリアントを生成する必要があります。置換は一方のバリアントで実行され、もう一方のバリアントでは実行されません。文字列について'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 への有効な引数を受け入れるようにアプローチを拡張または変更するにはどうすればよいでしょうか (グループ参照を解釈するためのパーサーを作成する必要はありません)。

4

2 に答える 2

1

substマッチ データにアクセスする callable を作成することを考えていたところ、最終的に について学びまし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

ただし、これが対象文字列を参照する際に必要なすべての柔軟性をカバーし、対応する一致に結び付けられるかどうかはわかりません。分割文字列のインデックス付きべき乗セットが頭に浮かびましたが、それは前述のパーサーからそう遠くないと思います。

于 2016-01-06T19:14:36.637 に答える