簡體   English   中英

Python:訪問嵌套列表中最里面的列表的元素

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM