array - reduce python 3
python: ¿se puede traducir en listas de comprensión como map, lambda y filter? (4)
Cuando programo en python, ahora evito map
, lambda
y filter
utilizando las comprensiones de listas porque es más fácil de leer y más rápido de ejecutar. Pero, ¿se puede reemplazar también la reduce
?
Por ejemplo, un objeto tiene un operador union()
que funciona en otro objeto, a1.union(a2)
, y da un tercer objeto del mismo tipo.
Tengo una lista de objetos:
L = [a1, a2, a3, ...]
Cómo tener la unión () de todos estos objetos con listas de comprensión, el equivalente de:
result = reduce(lambda a, b :a.union(b), L[1:], L[0])
Como la comprensión de una lista genera otra lista, no puede usarla para generar un solo valor. No son para eso. (Bueno ... hay un truco desagradable que usa un detalle de implementación filtrado en versiones antiguas de python que puede hacerlo. Ni siquiera voy a copiar el código de ejemplo aquí. No hagas esto).
Si estás preocupado por los aspectos estilísticos de reduce()
y su estilo, no lo estés. Nombra tus reducciones y estarás bien. Así que mientras
all_union = reduce(lambda a, b: a.union(b), L[1:], L[0])
no es genial, esto
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)
es bastante claro
Si te preocupa la velocidad, revisa los paquetes toolz y cytoolz , que son ''rápidos'' y ''increíblemente rápidos'', respectivamente. En grandes conjuntos de datos, a menudo le permitirán evitar procesar sus datos más de una vez o cargar todo el conjunto en la memoria a la vez, en contraste con las listas de comprensión.
No es ningún secreto que reducir no está entre las funciones favorecidas de los pitonistas.
En general, reduce es un pliegue a la izquierda en una lista.
Conceptualmente es fácil escribir un pliegue en Python que se pliegue a la izquierda o a la derecha en un iterable:
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
Sin un truco atroz, esto no se puede replicar en una comprensión porque no hay una función de tipo acumulador en una comprensión.
Simplemente use reducir, o escriba uno que tenga más sentido para usted.
Realmente no. Las comprensiones de listas son más similares al map
y, posiblemente, al filter
.
Un uso común de reducir es aplanar una lista de listas. Puede utilizar una lista de comprensión en su lugar.
L = [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
con reducir
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]
con lista comp
flattened = [item for sublist in L for item in sublist]
print(flattened)
[1, 2, 3, 2, 3, 4, 3, 4, 5]
Si su problema se puede resolver operando en la lista plana, este es un reemplazo efectivo. Contraste estas frases para el ejemplo dado:
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}