我有一个这样的字符串:
"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)
#
免责声明:请注意我对修复此代码不感兴趣。我问的是否有比我更好的方法。
答案 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)