在python中编程时,我现在通过使用列表推导来避免使用map
,lambda
和filter
,因为它更容易阅读并且执行速度更快。但是reduce
也可以被替换吗?
E.g。一个对象有一个运算符union()
,它可以处理另一个对象a1.union(a2)
,并提供相同类型的第三个对象。
我有一个对象列表:
L = [a1, a2, a3, ...]
如何将所有这些对象的union()与列表推导相对应,相当于:
result = reduce(lambda a, b :a.union(b), L[1:], L[0])
答案 0 :(得分:18)
减少是Pythonistas的not among the favored functions并不是秘密。
在Python中编写折叠在概念上很容易在可迭代上向左或向右折叠:
def fold(func, iterable, initial=None, reverse=False):
x=initial
if reverse:
iterable=reversed(iterable)
for e in iterable:
x=func(x,e) if x is not None else e
return x
如果没有一些残暴的黑客,这不能在理解中复制,因为在理解中没有累加器类型函数。
只需使用reduce - 或者写一个对你更有意义的东西。
答案 1 :(得分:4)
不是真的。列表推导更类似于map
,可能还有filter
。
答案 2 :(得分:4)
由于列表推导在定义上生成另一个列表,因此您无法使用它来生成单个值。 不是。 (嗯......有this nasty trick在旧版本的python中使用泄漏的实现细节,可以做到这一点。我甚至不会在这里复制示例代码。不要这样做。)
如果您担心reduce()
及其同类的风格方面,请不要这样做。命名你的减少,你会没事的。所以,同时:
all_union = reduce(lambda a, b: a.union(b), L[1:], L[0])
不是很好,这个:
def full_union(input):
""" Compute the union of a list of sets """
return reduce(lambda a, b: a.union(b), input[1:], input[0])
result = full_union(L)
很清楚。
如果你担心速度,分别检查toolz和cytoolz包,这些包分别是'快'和'疯狂'。在大型数据集上,与列表推导相比,它们通常会让您避免多次处理数据或将整个数据集一次加载到内存中。
答案 3 :(得分:2)
reduce的常见用法是压缩列表列表。您可以改用列表理解。
L = [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
from functools import reduce # python 3
flattened = reduce(lambda x, y: x + y, L)
print(flattened)
[1, 2, 3, 2, 3, 4, 3, 4, 5]
flattened = [item for sublist in L for item in sublist]
print(flattened)
[1, 2, 3, 2, 3, 4, 3, 4, 5]
如果您可以通过在展平列表上操作来解决问题,这是一个有效的替代方案。对比给定示例的这些单行:
all_union = reduce(lambda a, b: set(a).union(set(b)), L)
{1, 2, 3, 4, 5}
all_union = set([item for sublist in L for item in sublist])
{1, 2, 3, 4, 5}