Python:访问嵌套列表中最内层列表的元素

问题描述:

如果我有如下嵌套列表,我如何首先访问['*', '5', '8'](最内层列表),以便我可以执行乘法运算,然后移动到下一个最内层列表,即['*',[result_from_previous_step],'9']等等上至最外层列表中找到Python:访问嵌套列表中最内层列表的元素

['*', ['*', ['*', '5', '8'], '9'], '10'] 

这似乎有些什么样的评估树给我,但在自下而上的方式

+0

你试图达到那个目的的是什么? – ettanany

+0

这与评估一棵树完全相同 - 您只需在每一步中确定操作数是否为树并递归评估它们。如果他们不是树(他们是树叶),那么你跳过评估那个分支并且评估表达式。 – mgilson

+0

@ettanany我不知道如何去做这件事,但就像我说的在我的问题是想通过评估树达到这 – jack

最简单的解决办法是写一个自称评估内部递归函数表达式。

# 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 
+0

此外,还有一个“操作员”模块来执行数学运算 –

+2

是的,你可以编写代码使用字典和“操作员”功能;我只是不想过分地嘲笑他。 :-) – 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'])