最近,我收到了一个面试问题,说要转换字符串表达式,如" 1 + 2-3"和" -2 + 4"分别为0和2。假设输入是单位数字后跟符号而没有NULL输入。我试过这个输出,但面试官说我很接近但不是完美的解决方案。请帮帮我。感谢。
def ans(input):
result, j = 0, 0
for i in input:
if i == '+' or i == '-':
j = i
else:
i = int(i)
result = result j i
return result
ans("1+2-3")
ans("-2+4")
我犯了一些愚蠢的错误,但我正在学习。提前谢谢。
答案 0 :(得分:5)
两件事需要修复工作:
您需要正确处理初始值;当初始值为非负值时,此操作失败。在循环之前,设置j = '+'
以便添加一个非符号前缀值(同样,对于样式点,j
是一个可怕的名称,您可以使用op
或其他什么吗?)。< / p>
您不能将变量用作运算符。
替换:
result = result j i
使用:
if j == '+':
result += i
else:
result -= i
注意:如果允许模块,可以使用泛化来处理运算符&#34; nice&#34;方式(虽然需要更多的工作来遵守运营商的优先权)。你定义了:
import operator
ops = {'+': operator.add, '-': operator.sub, ...}
然后设置op
operator.add
的初始值并将运算符的测试更改为:
if i in ops:
op = ops[i]
else:
result = op(result, int(i))
可扩展到更多运算符,动态选择要执行的操作,而无需级联if
/ elif
检查。
旁注:虽然违反了挑战的精神,ast.literal_eval
(至少从Python 3.5开始,这可能会改变,请参阅bug #22525)实际上会安全地解析这样的字符串({{ 1}}是不安全的,因为它可以执行任意代码,但eval
只能解析Python文字,显然是一些基本的编译时数学)。所以你可以这样做:
ast.literal_eval
当然,它也处理许多其他文字,但我们从未定义过失败案例行为。 : - )
答案 1 :(得分:1)
使用 eval()是最简单的解决方案。像
eval("1+2-3")
以下代码提供了另一种不使用内置 eval
的解决方案import operator
class Parse(object):
def __init__(self, input):
self.input = input
self.pos = 0
self.end = len(input)
def eval(self):
result = self.match_digits()
while self.pos < self.end:
op = self.match_operator()
operand = self.match_digits()
result = op(result, operand)
return result
def match_operator(self):
look_ahead = self.input[self.pos]
self.advance()
return operator.add if look_ahead == '+' else operator.sub
def match_digits(self):
look_ahead = self.input[self.pos]
positive = 1
if look_ahead == '-':
positive = -1
self.advance()
digits, s = 0, self.pos
while s < self.end and self.input[s].isdigit():
digits = digits * 10 + int(self.input[s])
s += 1
self.advance(s-self.pos)
return digits * positive
def advance(self, offset=1):
self.pos += offset
进行测试
p = Parse(input='2+1+0-3')
print p.eval()
p = Parse(input='-2+-13+3')
print p.eval()
答案 2 :(得分:1)
我认为最灵活的解决方案(不使用eval
并且能够处理任何操作)是将字符串解析为二进制(红黑)树,其中叶子是数字和分支运算符(+, - ,/ *等)。
例如,"1+(5*12)/17"
将被解析为以下结构:
"+"
/ \
1 "/"
/ \
"()" 17
/
"*"
/ \
5 12
一旦你将一个字符串解析为这个结构,通过遍历分支深度优先,从右到左,它很容易计算。
如果您需要处理变量,那么您必须得到locals()
并相应地替换,无论是在解析字符串时,还是在遍历树时。
编辑:
我创建了一个工作示例来说明这一点,您可以在github上找到源代码:https://github.com/MJWunderlich/py-math-expression-evaluator
答案 3 :(得分:-1)
怎么样:
def f(s):
s = s.strip()
for i, c in enumerate(s):
if c == '+':
return f(s[:i]) + f(s[i+1:])
if c == '-':
return f(s[:i]) - f(s[i+1:])
for i, c in enumerate(s):
if c == '*':
return f(s[:i]) * f(s[i+1:])
if c == '/':
return f(s[:i]) / f(s[i+1:])
return 0 if s == '' else int(s)
?不适用于括号