2016-11-23 223 views
0

如果我有如下嵌套列表,我如何首先訪問['*', '5', '8'](最內層列表),以便我可以執行乘法運算,然後移動到下一個最內層列表,即['*',[result_from_previous_step],'9']等等上至最外層列表中找到Python:訪問嵌套列表中最內層列表的元素

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

這似乎有些什麼樣的評估樹給我,但在自下而上的方式

+0

你試圖達到那個目的的是什麼? – ettanany

+0

這與評估一棵樹完全相同 - 您只需在每一步中確定操作數是否爲樹並遞歸評估它們。如果他們不是樹(他們是樹葉),那麼你跳過評估那個分支並且評估表達式。 – mgilson

+0

@ettanany我不知道如何去做這件事,但就像我說的在我的問題是想通過評估樹達到這 – jack

回答

3

最簡單的解決辦法是寫一個自稱評估內部遞歸函數表達式。

# 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

0

您可以使用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是不是安全,因爲它執行字符串的內容不管它有什麼。所以,對於你傳遞給它

0

什麼這是你的問題

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()或嘗試/除非像我那樣。集合模塊在這種情況下不是很有用,因爲列表和字符串都是序列。

0

下面是上面提出的「更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'])