[英]Python : Accessing elements of inner most list in nested lists
如果我的嵌套列表如下,如何首先訪問['*', '5', '8']
(最里面的列表),以便我可以執行乘法運算,然后移至下一個最里面的列表,即['*',[result_from_previous_step],'9']
,依此類推,直到找到最外面的列表
['*', ['*', ['*', '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
這是您問題的粗略解決方案
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()或try / except。 在這種情況下,集合模塊不是很有用,因為列表和字符串都是序列。
您可以使用eval
創建自定義遞歸函數,以實現以下目的:
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是不安全的,因為無論它具有什么內容,它都會執行字符串的內容。 因此,請確保您傳遞給它的內容
這是上述kindall提出的“更Python化”且更易於擴展的版本。 它還不假定數字是整數。
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'])
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.