mapped from python reduce

python - from - ¿Cómo funciona la función reducir?



python zip (8)

Por lo que yo entiendo, la función de reducción toma una lista l y una función f . Luego, llama a la función f en los primeros dos elementos de la lista y luego llama repetidamente a la función f con el siguiente elemento de lista y el resultado anterior.

Entonces, defino las siguientes funciones:

La siguiente función calcula el factorial.

def fact(n): if n == 0 or n == 1: return 1 return fact(n-1) * n def reduce_func(x,y): return fact(x) * fact(y) lst = [1, 3, 1] print reduce(reduce_func, lst)

Ahora, ¿no debería esto darme ((1! * 3!) * 1!) = 6 ? Pero, en cambio da 720 . ¿Por qué 720 ? Parece tomar el factorial de 6 también. Pero, necesito entender por qué.

¿Alguien puede explicar por qué sucede esto y una solución alternativa?

Básicamente quiero calcular el producto de factoriales de todas las entradas en la lista. El plan de copia de seguridad es ejecutar un bucle y computarlo. Pero, preferiría usar reducir.


Bueno, primero que todo, su reduce_func no tiene la estructura de un pliegue; no coincide con su descripción de un pliegue (que es correcto).

La estructura de un pliegue es: def foldl(func, start, iter): return func(start, foldl(func, next(iter), iter)

Ahora, su función de fact no opera en dos elementos, solo calcula factorial.

Entonces, en resumen, no está utilizando un pliegue, y con esa definición de factorial, no necesita hacerlo.

Si quieres jugar con factorial, echa un vistazo al combinador de y: http://mvanier.livejournal.com/2897.html

Si desea obtener información sobre los pliegues, mire mi respuesta a esta pregunta, que demuestra su uso para calcular fracciones acumulativas: crear un porcentaje acumulativo a partir de un diccionario de datos


Desde el Python reduce documentación ,

reduce (función, secuencia) devuelve un solo valor construido llamando a la función (binaria) en los dos primeros elementos de la secuencia, luego en el resultado y el siguiente elemento, y así sucesivamente.

Entonces, paso a través. Calcula reduce_func de los primeros dos elementos, reduce_func(1, 3) = 1! * 3! = 6 reduce_func(1, 3) = 1! * 3! = 6 reduce_func(1, 3) = 1! * 3! = 6 . Luego, calcula reduce_func del resultado y el siguiente elemento: reduce_func(6, 1) = 6! * 1! = 720 reduce_func(6, 1) = 6! * 1! = 720 reduce_func(6, 1) = 6! * 1! = 720 .

Te perdiste eso, cuando el resultado de la primera llamada reduce_func se pasa como entrada al segundo, se factoriza antes de la multiplicación.


La forma más fácil de entender reduce () es mirar su código equivalente de Python puro:

def myreduce(func, iterable, start=None): it = iter(iterable) if start is None: try: start = next(it) except StopIteration: raise TypeError(''reduce() of empty sequence with no initial value'') accum_value = start for x in iterable: accum_value = func(accum_value, x) return accum_value

Puedes ver que solo tiene sentido que tu reduce_func () aplique el factorial al argumento más a la derecha:

def fact(n): if n == 0 or n == 1: return 1 return fact(n-1) * n def reduce_func(x,y): return x * fact(y) lst = [1, 3, 1] print reduce(reduce_func, lst)

Con esa pequeña revisión, el código produce 6 como esperabas :-)


Las otras respuestas son geniales. Simplemente agregaré un ejemplo ilustrado que me parece bastante bueno de entender reduce() :

>>> reduce(lambda x,y: x+y, [47,11,42,13]) 113

Se computará de la siguiente manera:

( Source ) ( mirror )


Ok lo tengo:

Necesito asignar los números a sus factoriales primero y luego llamar a reducir con el operador multiplicar.

Entonces, esto funcionaría:

lst_fact = map(fact, lst) reduce(operator.mul, lst_fact)


Reducir ejecuta la función en el parámetro # 1 sucesivamente a través de los valores proporcionados por el iterador en el parámetro # 2

print ''-------------- Example: Reduce(x + y) --------------'' def add(x,y): return x+y x = 5 y = 10 import functools tot = functools.reduce(add, range(5, 10)) print ''reduce(''+str(x)+'',''+str(y)+'')='' ,tot def myreduce(a,b): tot = 0 for i in range(a,b): tot = tot+i print i,tot print ''myreduce(''+str(a)+'',''+str(b)+'')='' ,tot myreduce(x,y) print ''-------------- Example: Reduce(x * y) --------------'' def add(x,y): return x*y x = 5 y = 10 import functools tot = functools.reduce(add, range(5, 10)) print ''reduce(''+str(x)+'',''+str(y)+'')='' ,tot def myreduce(a,b): tot = 1 for i in range(a,b): tot = tot * i print i,tot print ''myreduce(''+str(a)+'',''+str(b)+'')='' ,tot myreduce(x,y)


Su función llama a fact() en ambos argumentos . Estás calculando ((1! * 3!)! * 1!) . La solución es solo invocarlo solo en el segundo argumento y pasar a reduce() un valor inicial de 1.


También podrías implementar factorial utilizando reducir.

def factorial(n): return(reduce(lambda x,y:x*y,range(n+1)[1:]))