简体   繁体   English

python:reduce 可以转换为列表推导式,如 map、lambda 和 filter?

[英]python : can reduce be translated into list comprehensions like map, lambda and filter?

When programming in python, I now avoid map , lambda and filter by using list comprehensions because it is easier to read and faster in execution.在 Python 中编程时,我现在通过使用列表lambda避免使用maplambdafilter ,因为它更易于阅读且执行速度更快。 But can reduce be replaced as well?但是reduce可以被替换吗?

Eg an object has an operator union() that works on another object, a1.union(a2) , and gives a 3rd object of same type.例如,一个对象有一个操作符union() ,它作用于另一个对象a1.union(a2) ,并给出相同类型的第三个对象。

I have a list of objects:我有一个对象列表:

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

How to have the union() of all these objects with list comprehensions, the equivalent of:如何让所有这些对象的 union() 具有列表推导式,相当于:

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

It is no secret that reduce is not among the favored functions of the Pythonistas.众所周知,reduce不是Pythonistas最喜欢的功能之一。

Generically, reduce is a left fold on a list通常, reduce列表上的左折叠

It is conceptually easy to write a fold in Python that will fold left or right on a iterable:在 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

Without some atrocious hack, this cannot be replicated in a comprehension because there is not accumulator type function in a comprehension.如果没有一些残暴的 hack,这无法在理解中复制,因为理解中没有累加器类型的函数。

Just use reduce -- or write one that makes more sense to you.只需使用reduce——或者写一个对你更有意义的。

Since a list comprehension definitionally generates another list, you can't use it to generate a single value.由于列表推导式定义生成另一个列表,因此您不能使用它来生成单个值。 The aren't for that.不是为了那个。 (Well... there is this nasty trick that uses a leaked implementation detail in old versions of python that can do it. I'm not even going to copy the example code here. Don't do this.) (嗯......有一个讨厌的技巧,它在旧版本的python中使用泄露的实现细节可以做到这一点。我什至不打算在这里复制示例代码。不要这样做。)

If you're worried about the stylistic aspects of reduce() and its ilk, don't be.如果您担心reduce()及其同类的风格方面,请不要担心。 Name your reductions and you'll be fine.说出你的减少,你会没事的。 So while:所以同时:

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

isn't great, this:不是很好,这个:

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)

is pretty clear.很清楚。

If you're worried about speed, check out the toolz and cytoolz packages, which are 'fast' and 'insanely fast,' respectively.如果您担心速度,请查看toolzcytoolz软件包,它们分别是“快速”和“非常快”。 On large datasets, they'll often let you avoid processing your data more than once or loading the whole set in memory at once, in contrast to list comprehensions.在大型数据集上,与列表推导式相比,它们通常会让您避免多次处理数据或一次将整个数据集加载到内存中。

Not really.并不真地。 List comprehensions are more similar to map , and possibly filter .列表推导式更类似于map ,可能还类似于filter

A common use of reduce is to flatten a list of lists. reduce 的一个常见用途是展平列表列表。 You can use a list comprehension instead.您可以改用列表理解。

L = [[1, 2, 3], [2, 3, 4], [3, 4, 5]]

with reduce与减少

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]

with list comp与列表组合

flattened = [item for sublist in L for item in sublist]

print(flattened)

[1, 2, 3, 2, 3, 4, 3, 4, 5]

If your problem can be solved by operating on the flattened list, this is an effective replacement.如果您的问题可以通过对扁平列表进行操作来解决,那么这是一个有效的替代方法。 Contrast these one-liners for the given example:对比给定示例的这些单行:

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}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM