如何实现计算字符串列表形式数学表达式的calculate函数?
实现基于tokens列表的数学表达式计算函数
需求
给定如下形式的字符串tokens列表,需要实现一个calculate函数计算表达式结果:
tokens = ["6", "+", "8"] result = calculate(tokens) # 预期结果14
你尝试的实现思路:
while has_operator(tokens): operator_str, operator_pos = find_next_operator(tokens) left = tokens[operator_pos - 1] # 运算符左侧的数字 right = tokens[operator_pos + 1] # 运算符右侧的数字 result = evaluate(left, right, operator_str) # 求值函数 tokens[operator_pos-1:operator_pos+2] = [result] # 替换回列表 final_result = int(tokens[0]) # 示例流程: # ['2', '*', '3', '+', '4'] # ['6', '+', '4'] # ['10'] # result = 10
你的疑问:
- 当运算符与数字存储在同一数组中时,该逻辑如何正确运作?
- 如何将字符串形式的运算符转换为可执行的实际运算符?
疑问解答
1. 同一数组中运算符与数字共存时的逻辑运作原理
你的思路本质是迭代式表达式化简,核心逻辑是每次定位一个运算符,计算它左右两个数字的结果,再用这个结果替换掉「左数+运算符+右数」这三个元素,重复这个过程直到列表只剩一个元素——也就是最终结果。
这个逻辑能跑通的关键在于:
- 每次操作都会把3个元素合并成1个,列表长度每次减少2,必然会收敛到只剩1个元素
- 只要
find_next_operator能精准定位目标运算符(如果要支持优先级,就得先找乘除再找加减;如果是从左到右无优先级计算,就找第一个出现的运算符),替换操作就能精准覆盖并更新列表
拿你给的例子['2', '*', '3', '+', '4']来说:
第一次找到第一个运算符*,计算2*3=6,把列表的0-2位替换成['6'],列表变成['6', '+', '4'];
第二次找到运算符+,计算6+4=10,替换0-2位成['10'],循环结束直接取这个值就是结果。
2. 字符串转可执行运算符的实现方法
有几种简单直接的实现方式:
方法1:字典映射运算符到计算逻辑
用字典把字符串运算符对应到lambda函数,简洁直观:
operator_map = { '+': lambda a, b: a + b, '-': lambda a, b: a - b, '*': lambda a, b: a * b, '/': lambda a, b: a / b # 需要整数除法的话换成//,按需调整 } def evaluate(left_str, right_str, op_str): left = int(left_str) right = int(right_str) # 计算后转成字符串,保持tokens列表元素类型一致 return str(operator_map[op_str](left, right))
方法2:条件判断分支
如果不想用lambda,直接写if-elif逻辑也很清晰:
def evaluate(left_str, right_str, op_str): left = int(left_str) right = int(right_str) if op_str == '+': return str(left + right) elif op_str == '-': return str(left - right) elif op_str == '*': return str(left * right) elif op_str == '/': return str(left / right) else: raise ValueError(f"不支持的运算符: {op_str}")
方法3:用eval(不推荐)
虽然可以用eval(f"{left}{op_str}{right}")直接计算,但如果tokens列表可能包含不可信内容,这种方式会有安全风险,生产环境别用。
另外,你还需要补充实现思路里的辅助函数:
def has_operator(tokens): operators = {'+', '-', '*', '/'} return any(token in operators for token in tokens) def find_next_operator(tokens): # 从左到右找第一个运算符,要支持优先级的话这里要先遍历乘除 operators = {'+', '-', '*', '/'} for idx, token in enumerate(tokens): if token in operators: return token, idx raise ValueError("列表中没有运算符")
内容的提问来源于stack exchange,提问作者Filou
相关产品推荐
相关产品推荐

