5

次のような文字列があります。

"foo 15 bar -2hello 4 asdf+2"

私は取得したい:

"foo 14 bar -3hello 3 asdf+1"

すべての数値 (符号付きの 10 進整数としての数字のシーケンス) を、数値ごとに 1 つずつ、それぞれに対して実行された減算の結果に置き換えたいと思います。

文字を反復処理し、記号、数字、その他のテキストを分離し、関数を適用してパーツを再結合する ~50 の LOC 関数を作成しました。1 つの問題がありますが、質問に対する私の意図は、それを確認することではありません。代わりに、これを解決するためのpythonicの方法は何ですか?もっと簡単な方法はありますか?

参考までに、ここに既知の問題がある私の関数がありますが、私の意図はレビューを求めるのではなく、代わりに最もpythonicな方法を見つけることです.

Janne Karilaの賢明なコメントに答えるために編集します。

  • 優先: 与えられた場合は符号を保持:+2なる必要があります+1
  • 推奨: ゼロには符号がありません:+1なる必要があります0
  • 推奨: スペースなし:asdf - 4になるasdf - 3
  • 必須: 1 つだけ記号:-+-2なる-+-3

一般的な要求に応じて編集ここに私のバグのあるコードがあります:)

免責事項: このコードを修正するつもりはないことに注意してください。私のようなものよりも優れたアプローチがあるかどうかを尋ねています。

def apply_to_digits(some_str,handler):
    sign = "+"
    started = 0
    number = []
    tmp = []
    result = []
    for idx,char in enumerate(some_str):
        if started:
            if not char.isdigit():
                if number:
                    ss = sign + "".join(number)
                    rewritten = str(handler(int(ss)))
                    result.append(rewritten)
                elif tmp:
                    result.append("".join(tmp))
                number = []
                tmp = []
                sign = "+"
                started = 0
                # char will be dealt later
            else:
                number.append(char)
                continue
        if char in "-+":
            sign = char
            started = 1
            if tmp:
                result.append("".join(tmp))
                tmp = []
            tmp.append(char)
            continue
        elif char.isdigit():
            started = 1
            if tmp:
                result.append("".join(tmp))
                tmp = []
            number.append(char)
        else:
            tmp.append(char)
    if number:
        ss = sign + "".join(number)
        rewritten = str(handler(int(ss)))
        result.append(rewritten)
    if tmp:
        result.append("".join(tmp)), tmp
    return "".join(result)
#

免責事項: このコードを修正するつもりはないことに注意してください。私のようなものよりも優れたアプローチがあるかどうかを尋ねています。

4

1 に答える 1

12

正規表現を使用してみてくださいre.sub

>>> pattern = "(-?\d+)|(\+1)"
>>> def sub_one(match):
        return str(int(match.group(0)) - 1)

>>> text = "foo 15 bar -2hello 4 asdf+2"
>>> re.sub(pattern, sub_one, text)
'foo 14 bar -3hello 3 asdf+1'

正規表現(-?\d+)|(\+1)は、オプションの-記号と 1 つ以上の数字、またはリテラル シーケンスのいずれかをキャプチャします+1。そうすれば、正規表現は、数字を変換する際のすべての要件が適切に機能することを確認します。

ほとんどの場合、正規表現(-?\d+)自体は正しいこと(\+1)を行いますが、文字列+1が符号なしで常にゼロに変換されるようにするために存在します。気が変わって+1に変換したい+0場合は、正規表現の最初の部分のみを使用できます: (-?d+).

必要に応じて、これをすべてワンライナーに圧縮できます。

def replace_digits(text):
    return re.sub("(-?\d+)|(\+1)", lambda m: str(int(m.group(0)) - 1), text)
于 2013-10-29T14:22:34.730 に答える