Use list of nested indices to access list element

2019-09-16 05:31发布

问题:

How can a list of indices (called "indlst"), such as [[1,0], [3,1,2]] which corresponds to elements [1][0] and [3][1][2] of a given list (called "lst"), be used to access their respective elements? For example, given

    indlst = [[1,0], [3,1,2]]
    lst = ["a", ["b","c"], "d", ["e", ["f", "g", "h"]]]
    (required output) = [lst[1][0],lst[3][1][2]]

The output should correspond to ["b","h"]. I have no idea where to start, let alone find an efficient way to do it (as I don't think parsing strings is the most pythonic way to go about it).

EDIT: I should mention that the nested level of the indices is variable, so while [1,0] has two elements in it, [3,1,2] has three, and so forth. (examples changed accordingly).

回答1:

You can just iterate through and collect the value.

>>> for i,j in indlst:
...     print(lst[i][j])
... 
b
f

Or, you can use a simple list comprehension to form a list from those values.

>>> [lst[i][j] for i,j in indlst]
['b', 'f']

Edit:

For variable length, you can do the following:

>>> for i in indlst:
...     temp = lst
...     for j in i:
...         temp = temp[j]
...     print(temp)
... 
b
h

You can form a list with functions.reduce and list comprehension.

>>> from functools import reduce
>>> [reduce(lambda temp, x: temp[x], i,lst) for i in indlst]
['b', 'h']

N.B. this is a python3 solution. For python2, you can just ignore the import statement.



回答2:

you can try this code block:

required_output = []
for i,j in indlst:
    required_output.append(lst[i][j])


回答3:

Recursion can grab arbitrary/deeply indexed items from nested lists:

indlst = [[1,0], [3,1,2]]
lst = ["a", ["b","c"], "d", ["e", ["f", "g", "h"]]]
#(required output) = [lst[1][0],lst[3][1][2]]


def nested_lookup(nlst, idexs):
    if len(idexs) == 1:
        return nlst[idexs[0]]
    return nested_lookup(nlst[idexs[0]], idexs[1::])

reqout = [nested_lookup(lst, i) for i in indlst]
print(reqout) 

dindx = [[2], [3, 0], [0], [2], [3, 1, 2], [3, 0], [0], [2]]    
reqout = [nested_lookup(lst, i) for i in dindx]
print(reqout)
['b', 'h']
['d', 'e', 'a', 'd', 'h', 'e', 'a', 'd']  

I also found that arbitrary extra zero indices are fine:

    lst[1][0][0]
    Out[36]: 'b'

    lst[3][1][2]
    Out[37]: 'h'

    lst[3][1][2][0][0]
    Out[38]: 'h'

So if you actually know the max nesting depth you can fill in the index list values by overwriting your (variable number, shorter) index list values into the max fixed length dictionary primed with zeros using the .update() dictonary method
Then directly hard code the indices of nested list, which ignores any "extra" hard coded zero valued indices

below hard coded 4 depth:

def fix_depth_nested_lookup(nlst, idexs):
    reqout = []
    for i in idexs:
        ind = dict.fromkeys(range(4), 0)
        ind.update(dict(enumerate(i)))
        reqout.append(nlst[ind[0]][ind[1]][ind[2]][ind[3]])
    return reqout

print(fix_depth_nested_lookup(lst, indlst))
['b', 'h']