如果我有如下嵌套列表,我如何首先訪問['*', '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