练习:在Python中不使用列表推导式来映射或减少一个映射?

0 投票
3 回答
611 浏览
提问于 2025-04-15 16:53

当我开始写这个问题的时候,我没有想到用嵌套列表的简单解决方案,但现在我还是想找一个。

这是段很糟糕的代码:

fun0(
    fun1(fun2(fun3(arg1))),
    fun1(fun2(fun3(arg4))),
    fun1(fun2(fun3(arg4))),
    fun1(fun2(fun3(arg4))))

哎呀!这些名字只是举例。在实际应用中,它们的名字没有这样的规律。

我尝试了一下用 map(map ...)reduce(map ...),结果要么出错,要么出现 TypeError,然后才来到这里写这个问题。当然,简单的解决方案是在写问题的时候想到的:使用列表推导式。像这样(还没测试过):

fun0([i(j) for i in (fun1, fun2, fun3) for j in (arg1, arg2, arg3, arg4)])

不过,我还是想知道如何仅用函数式编程的工具来实现相同的效果呢?

fun0(map(fun1, map(fun2, map(fun3,
(arg1, arg2, arg3, arg4)))))

我觉得还有一个模式可以去掉。我试过 map(map, (fun1, ...), (arg1, ...)),但是这样做时,Python试图遍历每个参数,结果出错了。

3 个回答

-1

重写你第一个代码块的最有效方法是把三个函数组合在一起,然后把这个组合后的函数应用到参数列表上,最后再把fun0应用到这个列表上。Python本身没有很自然的方式来进行函数组合,所以你可能会像Jimmy的解决方案那样来处理。

不过,Python的风格通常不太鼓励使用lambda表达式,所以我可能会用列表推导式来代替map:

fun0(*[fun1(fun2(fun3(x))) for x in [arg1, arg2, arg3, arg4]])

编辑:我之前没注意到fun0需要的是单独的参数,而不是一个列表;根据Alex Martelli的帖子,添加了*

1
def composed(x): return fun1(fun2(fun3(x)))

fun0(*map(composed, (arg1, arg2, arg3, arg4)))

当然,你可以用一个 lambda 表达式来代替给中间函数起个名字叫 composed,不过我觉得这样写更容易理解。

要注意 * 这个符号非常重要,不然你就只是用一个参数(一个列表)在调用 fun0,而不是用四个参数来调用它!-)

2

你给出的三个例子做的事情各不相同。

你最开始的那个例子和下面这个是一样的:

fun0(map(lambda x:fun1(fun2(fun3(x))), [arg1,arg2,arg3,arg4])

而你第二个例子,如果你真的想要一个功能性的形式,可能是这样的:

fun0(map(apply, itertools.product([fun1,fun2,fun3],[arg1,arg2,arg3,arg4])))

撰写回答