用相应的减法结果替换字符串中的数字

时间:2013-10-29 13:56:03

标签: python regex string parsing replace

我有一个这样的字符串:

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

我想得到:

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

我想将每个数字(数字序列替换为有符号的基数为10的整数)替换为每个数字执行减法的结果,每个数字一个。

我写了一个~50 LOC函数,它迭代字符,分隔符号,数字和其他文本,应用函数并重新组合部分。虽然它有一个问题,但我对问题的意图是来审核它。相反,我试图问,解决这个问题的pythonic方法是什么,有更简单的方法吗?

供参考,here is my function已知问题,但我的目的是要求进行审核,而是找到最pythonic的方式。

修改以回答comment明智的Janne Karila

  • 首选:如果给定保留符号:+2应该成为+1
  • 首选:零无迹象:+1应变为0
  • 首选:无空格:asdf - 4变为asdf - 3
  • 必填:只有一个标志:-+-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)
#

免责声明:请注意我对修复此代码不感兴趣。我问的是否有比我更好的方法。

1 个答案:

答案 0 :(得分: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。这样,正则表达式将确保转换数字时的所有要求都能正常工作。

正则表达式(-?\d+)本身在大多数情况下做正确的事情,但(\+1)存在以确保字符串+1始终转换为零,没有符号。如果您改变主意,并希望+1转换为+0,那么您只能使用正则表达式的第一部分:(-?d+)

如果你愿意的话,你可以将这一切压缩成一行:

def replace_digits(text):
    return re.sub("(-?\d+)|(\+1)", lambda m: str(int(m.group(0)) - 1), text)