2016-11-26 47 views
2

我想寫入名爲foo的嵌套列表中的元素,但嵌套深度和索引僅在運行時在已知(非嵌套!)列表變量indexes中已知。訪問嵌套列表元素,運行時已知深度

例子:

如果indexes[4],我想foo[4]。我想要foo[4][7]

如果indexes[4,7,3],我想foo[4][7][3]

我能想到的是把命令字符串("foo[4][7][3]"在最後一個例子中)放在一起,然後調用eval。 這將是eval("foo["+']['.join([str(n) for n in indexes])+']')

工作,並且足夠短,但我希望更簡單,更pythonic的方式。

有沒有人知道任何替代品?

有沒有辦法不是分開處理空列表?如在:

如果indexes[],我想整個foo

這需要eval解決方案中的if

編輯:我需要寫入,而不是從元素讀取。我不認爲現有的兩個答案中的任何一個,或者所指定副本的答案都不能用於寫作。道歉誤導。

+0

不要使用'eval',請使用'ast.literal_eval'。 –

+3

'result = foo;索引中的索引:result = result [index];返回結果?沒有'eval'uating,字面或其他,並對待你想要的空'索引'。 – jonrsharpe

+0

@jonrsharpe更好!我寫了一個遞歸方法,但它不值得。 –

回答

3

可以使用reduce() function

from functools import reduce # Python 3 forward compatibility 
import operator 

def access(lst, indexes): 
    return reduce(operator.getitem, indexes, lst) 

可能使用list.__getitem__代替的operator.getitem,但是然後你將應用程序限制在列表對象中(它不適用於元組或字典,後者的機智h鍵而不是整數索引)。

這反覆將索引按順序應用到先前的結果(開始原始列表)。這符合所有標準,包括空列表情況:

>>> foo = ['a', 'b', 'c', 'd', ['foo', 'bar', 'baz', 'spam', 'eggs', 'ham', 'monty', ['alpha', 'beta', 'delta', 'gamma']]] 
>>> access(foo, []) 
['a', 'b', 'c', 'd', ['foo', 'bar', 'baz', 'spam', 'eggs', 'ham', 'monty', ['alpha', 'beta', 'delta', 'gamma']]] 
>>> access(foo, [4]) 
['foo', 'bar', 'baz', 'spam', 'eggs', 'ham', 'monty', ['alpha', 'beta', 'delta', 'gamma']] 
>>> access(foo, [4, 7]) 
['alpha', 'beta', 'delta', 'gamma'] 
>>> access(foo, [4, 7, 3]) 
'gamma' 

如果您需要分配到最後一個元素,保持最後指數一旁,然後分配到:

if indexes: 
    target = access(foo, indexes[:-1]) 
    target[indexes[-1]] = new_value 
else: 
    foo = new_value 
2

您可以設置itemfoo,然後繼續與索引列表訪問更深層次的嵌套元素:

def access (foo, indexes): 
    item = foo 
    for index in indexes: 
     item = item[index] 
    return item