python:reduce 可以翻译成 map、lambda 和 filter 之类的列表理解吗?
Posted
技术标签:
【中文标题】python:reduce 可以翻译成 map、lambda 和 filter 之类的列表理解吗?【英文标题】:python : can reduce be translated into list comprehensions like map, lambda and filter? 【发布时间】:2014-08-16 02:52:30 【问题描述】:在 python 中编程时,我现在通过使用列表推导来避免map
、lambda
和filter
,因为它更易于阅读且执行速度更快。但是reduce
也可以替换吗?
例如一个对象有一个运算符union()
,它作用于另一个对象a1.union(a2)
,并给出第三个相同类型的对象。
我有一个对象列表:
L = [a1, a2, a3, ...]
如何将所有这些对象的 union() 与列表推导式结合起来,相当于:
result = reduce(lambda a, b :a.union(b), L[1:], L[0])
【问题讨论】:
在某些情况下:没有。但取决于。请提供您想到的具体查询 @sshashank124 - 有什么例子吗? 集合并集是一个不好的例子,因为你可以简单地做result = set().union(*L)
,即使 L 是一个空列表,它也有工作的好处。无论如何,lambda a, b :a.union(b)
可以更简洁地写成set.union
,因为在 python 中obj.method(args)
与cls.method(obj, args)
相同
Guido 说要使用 for 循环而不是 reduce。他不喜欢 FP 结构。
【参考方案1】:
不是真的。列表推导更类似于map
和filter
。
【讨论】:
【参考方案2】:由于列表推导式定义会生成另一个列表,因此您不能使用它来生成单个值。不是为。 (嗯...有this nasty trick 使用旧版本python 中泄露的实现细节可以做到这一点。我什至不打算在这里复制示例代码。不要这样做。)
如果您担心reduce()
及其同类的风格方面,请不要担心。说出你的减少,你会没事的。所以虽然:
all_union = reduce(lambda a, b: a.union(b), L[1:], L[0])
不好,这个:
from functools import reduce
def full_union(input):
""" Compute the union of a list of sets """
return reduce(set.union, input[1:], input[0])
result = full_union(L)
很清楚。
如果您担心速度,请查看toolz 和cytoolz 包,它们分别是“快速”和“非常快”。在大型数据集上,与列表推导相比,它们通常可以让您避免多次处理数据或一次将整个数据集加载到内存中。
【讨论】:
要使reduce()
表达式本身可读,请使第一个参数不是 lambda。例如:reduce(set.union, <list of sets>)
有时这需要您在调用 reduce
之外的某个地方定义(并因此命名)运算符。【参考方案3】:
reduce 是 Python 达人的not among the favored functions,这已经不是什么秘密了。
一般来说,reduce 是 left fold on a list
在 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
如果没有一些残暴的 hack,这将无法在推导中复制,因为推导中没有累加器类型的函数。
只需使用 reduce —— 或者写一个对你更有意义的。
【讨论】:
【参考方案4】: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
【讨论】:
使用sum(L, [])
。也就是说,总和/列表推导会创建一个“完整”列表,而 reduce(operator.or_, map(set, L), set())
不会。以上是关于python:reduce 可以翻译成 map、lambda 和 filter 之类的列表理解吗?的主要内容,如果未能解决你的问题,请参考以下文章
在python中为Hadoop Map Reduce创建自定义可写键/值类型?