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')