如果我有如下嵌套列表,我如何首先访问['*', '5', '8']
(最内层列表),以便我可以执行乘法运算,然后移动到下一个最内层列表,即['*',[result_from_previous_step],'9']
等等上至最外层列表中找到Python:访问嵌套列表中最内层列表的元素
['*', ['*', ['*', '5', '8'], '9'], '10']
这似乎有些什么样的评估树给我,但在自下而上的方式
如果我有如下嵌套列表,我如何首先访问['*', '5', '8']
(最内层列表),以便我可以执行乘法运算,然后移动到下一个最内层列表,即['*',[result_from_previous_step],'9']
等等上至最外层列表中找到Python:访问嵌套列表中最内层列表的元素
['*', ['*', ['*', '5', '8'], '9'], '10']
这似乎有些什么样的评估树给我,但在自下而上的方式
最简单的解决办法是写一个自称评估内部递归函数表达式。
# helper function to parse strings where necessary
def intorfloat(number):
if not isinstance(number, str): # already parsed
return number
try:
return int(number)
except ValueError:
return float(number)
# evaluates a simple expression (no subexpressions)
def evaluate2(operation, operand1, operand2):
operand1, operand2 = intorfloat(operand1), intorfloat(operand2)
if operation == "*":
return operand1 * operand2
elif operation == "+":
return operand1 + operand2
elif operation == "/":
# keep the result an int if possible
result1 = operand1 // operand2
result2 = float(operand1)/operand2
return result1 if result1 == result2 else result2
elif operation == "-":
return operand1 - operand2
# recursively evaluate an expression with subexpressions
def evaluate(expression):
operation, operand1, operand2 = expression
if isinstance(operand1, list):
operand1 = evaluate(operand1)
if isinstance(operand1, list):
operand2 = evaluate(operand2)
return evaluate2(operation, operand1, operand2)
迭代解决方案也是可能的;优点是您可以评估任何深度的表达式。在这个版本中,我们继续下降到子列表中,直到找到一片叶子:一个没有任何子表达式的表达式。然后,我们评估叶片并将其替换为结果,并从头开始。最终,顶级表达式没有子表达式。
该算法实际上修改表达式,反复简化它,直到评估它为止很简单。 (递归解决方案不修改表达式。)
如果表达式很深,我们可能会执行大量不必要的遍历来重复查找叶节点。我们可以创建一个堆栈来让我们回溯,而不是每次都要从顶层开始,但是我们也可以在这一点上使用递归解决方案。
# uses intorfloat() and evaluate2() functions previously shown
def evaluate(expression):
while isinstance(expression[1], list) or isinstance(expression[2], list):
current = expression
container = None
while True: # find a leaf node
operation, operand1, operand2 = current
if isinstance(operand1, list):
container, slot = current, 1
current = operand1
elif isinstance(operand2, list):
container, slot = current, 2
current = operand2
else:
break
if container:
container[slot] = evaluate2(*current)
return evaluate2(*expression)
print evaluate(['*', ['*', ['*', '5', '8'], '9'], '10']) # 3600
此外,还有一个“操作员”模块来执行数学运算 –
是的,你可以编写代码使用字典和“操作员”功能;我只是不想过分地嘲笑他。 :-) – kindall
您可以使用eval
实现创建custome递归函数此为:
def perform_operation(my_list):
temp_list = []
for item in my_list:
if isinstance(item, list):
item = perform_operation(item)
temp_list.append(item)
return eval('{} {} {}'.format(temp_list[1], temp_list[0], temp_list[2]))
采样运行:
>>> my_list = ['*', ['*', ['*', '5', '8'], '9'], '10']
>>> perform_operation(my_list)
3600
注:使用eval是不是安全,因为它执行字符串的内容不管它有什么。所以,对于你传递给它
什么这是你的问题
l = ['*', ['*', ['*', '5', '8'], '9'], '10']
def islist(l):
try:
l.append
return True
except AttributeError:
return False
def reduce(l):
if islist(l):
return recurse(l)
else:
return l
def recurse(l):
if not islist(l):
return l
first = reduce(l[0])
second = reduce(l[1])
third = reduce(l[2])
return "({} {} {})".format(second, first, third)
print recurse(l)
的一个粗略的解决方案,它使用递归是肯定的。 Python不是实现递归算法的最佳语言,像Erlang这样的纯函数语言在这些主题上更加强大。
主要的问题是递归调用和内存占用的最大数量,但对于这样一个小的列表,这是有效的。
你可能遇到的一个问题是如何分辨列表和其他事情,这并不那么简单。您可以使用isinstance()或尝试/除非像我那样。集合模块在这种情况下不是很有用,因为列表和字符串都是序列。
下面是上面提出的“更Pythonic”和更容易扩展的版本。它也不认为这些数字是整数。
import operator
def evaluate(expression):
if isinstance(expression, str):
return float(expression)
op, operand1, operand2 = expression
ops = {"*" : operator.mul,
"+" : operator.add,
"/" : operator.truediv,
"-" : operator.sub}
return ops[op](evaluate(operand1), evaluate(operand2))
evaluate(['*', ['*', ['*', '5', '8'], '9'], '10'])
你试图达到那个目的的是什么? – ettanany
这与评估一棵树完全相同 - 您只需在每一步中确定操作数是否为树并递归评估它们。如果他们不是树(他们是树叶),那么你跳过评估那个分支并且评估表达式。 – mgilson
@ettanany我不知道如何去做这件事,但就像我说的在我的问题是想通过评估树达到这 – jack