I have an arbitrarily nested iterable like so:
numbers = (1, 2, (3, (4, 5)), 7)
and I\'d like to map a function over it without changing the st
We scan every element in the sequence, and proceeds into deeper recursion if the current item is a sub-sequence, or yields it's mapping if we reached a non-sequence data type (could be int, str, or any complex classes).
We use collections.Sequence to generalize the idea for every sequence, and not only tuples or lists, and type(item) upon yield to ensure that the sub-sequences we get back remains of the same type they were.
from collections import Sequence
def recursive_map (seq, func):
for item in seq:
if isinstance(item, Sequence):
yield type(item)(recursive_map(item, func))
else:
yield func(item)
Demo:
>>> numbers = (1, 2, (3, (4, 5)), 7)
>>> mapped = recursive_map(numbers, str)
>>> tuple(mapped)
('1', '2', ('3', ('4', '5')), '7')
Or a more complex example:
>>> complex_list = (1, 2, [3, (complex('4+2j'), 5)], map(str, (range(7, 10))))
>>> tuple(recursive_map(complex_list, lambda x: x.__class__.__name__))
('int', 'int', ['int', ('complex', 'int')], 'map')