Convert for loop to recursion to deep copy a nested list

Question:

Need your help in converting this function to use only recursion. Currently it’s using a for loop and recursion but it needs to use only recursion.
The function gets a list or a nested list and needs to return a copied list (deep copy!).

And I can not import deepcopy from copy or use list comprehension.

def my_deepcopy(nested_list: List[Any]) -> List[Any]:
    results = []
    for item in nested_list:
        if not isinstance(item, list):
            results.append(item)
        else:
            results.append(my_deepcopy(item))
    return results
Asked By: Avi Doe

||

Answers:

The standard way to turn an iterative function into a recursive function is to have a base case for an empty list, and then add the recursive result from the first list item to the results for the remaining list items. E.g.:

>>> def list_deepcopy(item):
...     if not isinstance(item, list) or not item:
...         return item
...     return [list_deepcopy(item[0])] + list_deepcopy(item[1:])
...
>>> a = [1, 2, [3, 4, [5, 6]]]
>>> b = list_deepcopy(a)
>>> a[0] *= 10
>>> a[2][0] *= 10
>>> a[2][2][0] *= 10
>>> a
[10, 2, [30, 4, [50, 6]]]
>>> b
[1, 2, [3, 4, [5, 6]]]
Answered By: Samwise

Method without slicing:

def list_deepcopy(lst, start=0):
    if not isinstance(lst, list):
        return lst
    if start == len(lst):
        return []

    return [list_deepcopy(lst[start])] + list_deepcopy(lst, start + 1)

Some test:

>>> a = [1, [2, [3, [4, [5]]]]]
>>> b = list_deepcopy(a)
>>> a
[1, [2, [3, [4, [5]]]]]
>>> b
[1, [2, [3, [4, [5]]]]]
>>> from functools import reduce
>>> from itertools import repeat
>>> from operator import getitem
>>> for i in range(5):
...     reduce(getitem, repeat(1, i), a)[0] *= 10
... 
>>> a
[10, [20, [30, [40, [50]]]]]
>>> b
[1, [2, [3, [4, [5]]]]]
Answered By: Mechanic Pig
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.