To avoid recursion, you need to implement your own stack. Here is an example. (I added a list_d
containing your list_c
and a scalar, in order to show leaf elements being found at different depths.)
list_a = ["string", 1.0, 1.0]
list_b = [1.0, "string", 1.0]
list_c = [list_a, list_b]
list_d = [2.0, list_c]
def walk_list(l):
if not l:
return
parent_lists = []
parent_indices = []
current_list = l
current_index = 0
while True:
# descend from current position through lists until
# leaf element or empty list is reached
while True:
val = current_list[current_index]
if not isinstance(val, list):
# found leaf element (result of interest)
yield (val,
parent_lists + [current_list],
parent_indices + [current_index])
break
elif not val:
# found empty list (ignore)
break
else:
# list to descend into
parent_indices.append(current_index)
parent_lists.append(current_list)
current_list = val
current_index = 0
# increment to next position, reascending to parent
# each time we go off the end of any list
while True:
current_index += 1
if current_index < len(current_list):
break
if not parent_lists:
return
current_list = parent_lists.pop()
current_index = parent_indices.pop()
print('Original: ', list_d)
print()
for val, lists, indices in walk_list(list_d):
print("saw value {} at position {}".format(repr(val), indices))
if isinstance(val, float):
lists[-1][indices[-1]] /= 2
print('\nFinal: ', list_d)
gives:
Original: [2.0, [['string', 1.0, 1.0], [1.0, 'string', 1.0]]]
saw value 2.0 at position [0]
saw value 'string' at position [1, 0, 0]
saw value 1.0 at position [1, 0, 1]
saw value 1.0 at position [1, 0, 2]
saw value 1.0 at position [1, 1, 0]
saw value 'string' at position [1, 1, 1]
saw value 1.0 at position [1, 1, 2]
Final: [1.0, [['string', 0.5, 0.5], [0.5, 'string', 0.5]]]
The lists
that comes back from the iterator is a list of increasingly deep sublists which are encountered in the path from the original list to the element in question, i.e. lists[0]
will contain the original list and lists[-1]
is the immediate parent list containing the value concerned.
Obviously if modifying the list while iterating over it, you need to be careful to only modify scalar values, not to modify its structure by appending or removing values from any list objects.