我需要解析只有次(*
)和添加(+
)的算术字符串,例如{{1} },使用正则表达式。
我的工作代码如下:
300+10*51+20+2*21
我想知道是否有办法避免在上面创建变量import re
input_str = '300+10*51+20+2*21'
#input_str = '1*2+3*4'
prod_re = re.compile(r"(\d+)\*(\d+)")
sum_re = re.compile(r"(\d+)\+?")
result = 0
index = 0
while (index <= len(input_str)-1):
#-----
prod_match = prod_re.match(input_str, index)
if prod_match:
# print 'find prod', prod_match.groups()
result += int(prod_match.group(1))*int(prod_match.group(2))
index += len(prod_match.group(0))+1
continue
#-----
sum_match = sum_re.match(input_str, index)
if sum_match:
# print 'find sum', sum_match.groups()
result += int(sum_match.group(1))
index += len(sum_match.group(0))
continue
#-----
if (not prod_match) and (not sum_match):
print 'None match, check input string'
break
print result
?
答案 0 :(得分:1)
算法似乎不正确。输入1*2+3*4
不会产生正确的结果。在解决一个乘法后你继续解决一个加法似乎是错误的,而在某些情况下,你必须先做更多的乘法才能进行任何加法。
通过对正则表达式和循环进行一些更改,您可以按照以下方式实现所需:
import re
input_str = '3+1*2+3*4'
# match terms, which may include multiplications
sum_re = re.compile(r"(\d+(?:\*\d+)*)(?:\+|$)")
# match factors, which can only be numbers
prod_re = re.compile(r"\d+")
result = 0
# find terms
for sum_match in sum_re.findall(input_str):
# for each term, determine its value by applying the multiplications
product = 1
for prod_match in prod_re.findall(sum_match):
product *= int(prod_match)
# add the term's value to the result
result += product
print (result)
这个正则表达式:
(\d+(?:\*\d+)*)(?:\+|$)
...匹配一个整数,后跟零次或多次乘法:
(?:\*\d+)*
(?:
使其成为非捕获组。如果没有?:
,方法findall
会将匹配的这一部分分配给我们不想要的单独的列表元素。
\*\d+
是:一个字面的星号后跟数字。
最终(?:\+|$)
也是一个非捕获组,需要跟随文字+
或输入结束($
)。
答案 1 :(得分:0)
问题的解决方案应该是term
之后的可能符号,后跟一个术语列表,由添加运算符分隔,如
[+-]?({term}([+-]{term})*)
其中每个术语是一个因子,后跟可能的乘法运算符的空列表和另一个因子,如下所示:
{factor}([*/]{factor})*
其中因子是数字序列[0-9]+
,所以替换,导致:
[+-]?([0-9]+([*/][0-9]+)*([+-][0-9]+([*/][0-9]+)*)*)
这将是一个可能的正则表达式,它假定您可以拥有的运算符之间的优先级结构。但是它不允许你提取不同的元素,正如很容易证明的那样:正则表达式里面只有4个组元素(左括号4)所以你只能匹配其中的四个(第一个术语,最后一个因子)第一个术语,最后一个术语,以及最后一个术语的最后一个因子。如果你开始用括号括起子表达式,你可以得到更多,但正则表达式中的组数是有限的事情,你可以构造一个可能无限长的正则表达式。
这说(你将无法将所有事物组与正则表达式结构分开)采用不同的方法:第一个符号是可选的,后面可以跟一个未定义的术语数,由乘法运算符分隔或添加的:
[+-]?([0-9]+([*/+-][0-9]+)*
也可以完成这项工作(它与同一组表达式匹配。即使你限制了只有一个运算符可以在1位或更多位数的任何序列中间隔的事实,所得到的正则表达式可以简化为:
[-+]?[0-9]([*/+-]?[0-9])*
或使用现今使用的常用符号:
[-+]?\d([*/+-]?\d)*