Daniel Casasampera
Daniel Casasampera

Reputation: 381

How to modify the content of a nested list?

I have some nested lists and I want to be able to modify them having the indexes of where the modification would take place.

One example of such lists is:

l2 = ['Node_50',
      ['Node_48', 'Node_23', ['Node_12', 'Node_3'], ['Node_20']],
      ['Node_22', ['Node_44'], ['Node_7', 'Node_40']]
     ]

I then have a new list of elements and a list cointaing the indexes

lnew = ['Node_1', 'Node_40', 'Node_17']
indexes = [1, 3]

I would like to get a function that replaces the element of the list at the indexes given by the newlist of values. The function would have to do that (for this example):

l2[1][3] = lnew

The lists can have any number of nested lists so the length of indexes may change. The fucntion would need to work for any nested list and for any number of indexes.

Upvotes: 0

Views: 95

Answers (3)

André Laszlo
André Laszlo

Reputation: 15537

I think that user8426627 has already given a great answer but if you prefer a functional style, you could do something like this:

>>> from functools import reduce
>>> from operator import getitem
>>> reduce(getitem, indexes[:-1], l2)[indexes[-1]] = lnew
>>> l2
['Node_50',
  ['Node_48', 'Node_23', ['Node_12', 'Node_3'], ['Node_1', 'Node_40', 'Node_17']],
  ['Node_22', ['Node_44'], ['Node_7', 'Node_40']]]

Upvotes: 2

user8426627
user8426627

Reputation: 943

shorter is :

l2 = ['Node_50',
      ['Node_48', 'Node_23', ['Node_12', 'Node_3'], ['Node_20']],
      ['Node_22', ['Node_44'], ['Node_7', 'Node_40']]
     ]


lnew = ['Node_1', 'Node_40', 'Node_17']
indexes = [1, 3]


def set_deep(root, indexes, value):

    for x in indexes[:-1]:
        root = root[x]
    root[indexes[-1]] = value


set_deep(l2, indexes, lnew)


print(l2)

Thinking about it, the feature list[iterable] should be added to Python. I think actualy numpy supports list[list] notation?

Upvotes: 2

Alfonso
Alfonso

Reputation: 713

You do not need a function, just assign the new list to the desired position and it will replace the previous value.

l2 = ['Node_50',
       ['Node_48', 'Node_23', ['Node_12', 'Node_3'], ['Node_20']],
       ['Node_22', ['Node_44'], ['Node_7', 'Node_40']]
      ]
lnew = ['Node_1', 'Node_40', 'Node_17']

before

l2[1][3]

returns

['Node_20']

then replace it

l2[1][3] = lnew

after

l2[1][3]

returns

['Node_1', 'Node_40', 'Node_17']

This can also be done with a function

def myFUN(LIST, newLIST, indexes):
    i,j = indexes
    if i >= len(LIST):
        print("list index (" + str(i) + ") out of range")
        return
    elif j >= len(LIST[i]):
        print("list index (" + str(j) + ") out of range")
        return
    else:
        LIST[i][j] = newLIST
        return LIST

now

myFUN(l2, lnew, indexes)

returns

['Node_50', ['Node_48', 'Node_23', ['Node_12', 'Node_3'], ['Node_1', 'Node_40', 'Node_17']], ['Node_22', ['Node_44'], ['Node_7', 'Node_40']]]

but

myFUN(l2, lnew, (4,1))

returns

list index (4) out of range

and

myFUN(l2, lnew, (1,25))

returns

list index (25) out of range

Keep the original list unchanged

For python3

def myFUN(LIST, newLIST, indexes):
    res = LIST.copy()
    i,j = indexes
    if i >= len(LIST):
        print("list index (" + str(i) + ") out of range")
        return
    elif j >= len(LIST[i]):
        print("list index (" + str(j) + ") out of range")
        return
    else:
        res[i][j] = newLIST
        return res

in python 2 use res = LIST[:] or res=list(LIST). Now

myFUN(l2, lnew, indexes)

returns

['Node_50', ['Node_48', 'Node_23', ['Node_12', 'Node_3'], ['Node_1', 'Node_40', 'Node_17']], ['Node_22', ['Node_44'], ['Node_7', 'Node_40']]]

but l2 remains unaltered

l2

returns

['Node_50', ['Node_48', 'Node_23', ['Node_12', 'Node_3'], ['Node_20']], ['Node_22', ['Node_44'], ['Node_7', 'Node_40']]]

Upvotes: 0

Related Questions