< Original code removed>
EDIT in response to comment.
This is going to be tricky, then. Note that, when you flatten list2, the final result no longer includes list1: we now have three new elements -- 3, 4, 5 -- in place of list1.
The trick, then, is to consider each element of the list in turn, recurring on that element first, replacing any list elements, and then returning to the caller.
So here is a solution that works. At each call, it iterates through the list, building a result list. Any list-type element of the input list gets fed to a recursive call.
The painful part of this is the case in which the list length alters, such as turning the 2-element list [1, [2, 3]] into the 3-element list [1, 2, 3]. To effect this change without changing the base object pointer, I work in three steps:
- Build a new list, the flattened version of the input list.
- Pop all of the elements out of the original list; this leaves an empty list, but under the original object handle.
- Append each element of the result list to the original list.
This preserves side effects to sub-elements of the original list. However, note that there is still no way to keep that relationship in place after the flattening: the original list no longer contains the sub-list; rather, it contains new references to the sub-list's elements, in order.
def flatten_in_place(lst):
# print "ENTER in_place", lst
result = []
for i in range(len(lst)):
if type(lst[i]) == type([]):
result.extend(flatten_in_place(lst[i]))
else:
result.append(lst[i])
# print "Loop", i, "result =", result
# print "After loop, lst =", lst
for _ in range(len(lst)):
lst.pop()
for _ in range(len(result)):
lst.append(result[_])
# print "LEAVE in_place", lst
return result
list1 = [3, 4, [[5]]]
list2 = [[[1, 2, list1], (6, [7]), 8], 9, False]
flatten_in_place(list2)
print ("list2 flattened", list2)
# [1, 2, 3, 4, 5, (6, [7]), 8, 9, False]
print ("list1 affected", list1)
# [3, 4, 5]
I'll leave any improvements as an exercise for the student -- or other SO denizens.