Python:在递归可迭代项上映射函数 [英] Python: Map a function over recursive iterables
问题描述
我有一个任意嵌套的可迭代对象,如下所示:
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 structure. For example, I might want to convert all the numbers to strings to get
strings = recursive_map(str, numbers)
assert strings == ('1', '2', ('3', ('4', '5')), '7')
有没有很好的方法可以做到这一点?我可以想象编写自己的方法来手动遍历数字
,但是我想知道是否存在一种通用的方法来映射递归可迭代对象.
Is there a nice way to do this? I can imaging writing my own method to manually traverse numbers
, but I'd like to know if there's a general way to map over recursive iterables.
另外,在我的示例中,如果 strings
给我嵌套列表(或一些可迭代的)而不是嵌套元组也可以.
Also, in my example, it's okay if strings
gives me nested lists (or some iterable) rather nested tuples.
推荐答案
我们扫描序列中的每个元素,如果当前项目是子序列,则进行更深层次的递归;如果到达非序列,则产生其映射.序列数据类型(可以是 int
, str
或任何复杂的类).
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).
我们使用 collections.Sequence
来概括每个序列的概念,不仅是元组或列表,还应在yield时使用 type(item)
来确保子序列序列我们得到的残骸类型与以前相同.
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)
演示:
>>> numbers = (1, 2, (3, (4, 5)), 7)
>>> mapped = recursive_map(numbers, str)
>>> tuple(mapped)
('1', '2', ('3', ('4', '5')), '7')
或更复杂的示例:
>>> 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')
这篇关于Python:在递归可迭代项上映射函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!