30

在 python 中编程时,我现在避免使用map,lambdafilter使用列表推导,因为它更易于阅读且执行速度更快。但是也reduce可以换吗?

例如,一个对象有一个union()对另一个对象起作用的运算符a1.union(a2),并给出第三个相同类型的对象。

我有一个对象列表:

L = [a1, a2, a3, ...]

如何使所有这些对象的 union() 具有列表推导,相当于:

result = reduce(lambda a, b :a.union(b), L[1:], L[0])
4

5 回答 5

20

众所周知,reduce不在 Pythonistas的青睐函数之列。

通常,reduce列表的左折叠

在 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 —— 或者写一个对你更有意义的。

于 2014-06-25T14:59:46.817 回答
8

由于列表推导式定义会生成另一个列表,因此您不能使用它来生成单个值。不是为了那个。(嗯......有一个讨厌的技巧,它在旧版本的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)

很清楚。

如果您担心速度,请查看toolzcytoolz包,它们分别是“快速”和“非常快”。在大型数据集上,与列表推导相比,它们通常会让您避免多次处理数据或一次将整个数据集加载到内存中。

于 2014-06-25T14:27:32.827 回答
4

并不真地。列表推导更类似于mapand filter

于 2014-06-25T13:52:26.780 回答
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}
于 2017-09-06T16:26:23.420 回答
0

不是联合最易读的化简,但赋值表达式可用于在单个表达式中解决它:

In [51]: L = [{1}, {2}, {3}, {4}, {5}]

In [52]: reduce(lambda a, b: a.union(b), L[1:], L[0])
Out[52]: {1, 2, 3, 4, 5}

In [53]: (s := set(), [s := s.union(x) for x in L][-1])[1]
Out[53]: {1, 2, 3, 4, 5}
于 2022-02-13T01:56:41.477 回答