Esto es bastante simple, pero estoy tratando de aprender / entender la programación funcional en python. El siguiente código:
foos = [1.0,2.0,3.0,4.0,5.0]
bars = [1,2,3]
def maptest(foo, bar):
print foo, bar
map(maptest, foos, bars)
produce:
1.0 1
2.0 2
3.0 3
4.0 None
5.0 None
P. ¿Hay alguna manera de usar map o cualquier otra herramienta funcional en python para producir lo siguiente sin bucles, etc.
1.0 [1,2,3]
2.0 [1,2,3]
3.0 [1,2,3]
4.0 [1,2,3]
5.0 [1,2,3]
Solo como nota al margen, ¿cómo cambiaría la implementación si hubiera una dependencia entre foo y bar? p.ej
foos = [1.0,2.0,3.0,4.0,5.0]
bars = [1,2,3,4,5]
e imprimir:
1.0 [2,3,4,5]
2.0 [1,3,4,5]
3.0 [1,2,4,5]
...
PD: Sé cómo hacerlo ingenuamente usando if, bucles y / o generadores, pero me gustaría aprender cómo lograrlo usando herramientas funcionales. ¿Es solo un caso de agregar una instrucción if a maptest o aplicar otro mapa de filtro a las barras internamente dentro de maptest?
python
dictionary
functional-programming
eusoubrasileiro
fuente
fuente
Respuestas:
La forma más fácil sería no pasar
bars
por las diferentes funciones, sino acceder directamente desdemaptest
:Con su
maptest
función original , también podría usar una función lambda enmap
:fuente
¿Conoces otros lenguajes funcionales? es decir, ¿estás tratando de aprender cómo Python hace la programación funcional, o estás tratando de aprender acerca de la programación funcional y usar Python como vehículo?
Además, ¿entiendes las comprensiones de listas?
es directamente equivalente (*) a:
De hecho, creo que
map()
una vez se programó la eliminación de Python 3.0 como redundante (eso no sucedió).es mayormente equivalente a:
(hay una diferencia en cómo maneja el caso en el que las secuencias son de diferente longitud. Como viste, completa
map()
None cuando una de las secuencias se agota, mientras que sezip()
detiene cuando se detiene la secuencia más corta)Entonces, para abordar su pregunta específica, está tratando de producir el resultado:
Puede hacer esto escribiendo una función que tome un solo argumento y lo imprima, seguido de barras:
Alternativamente, puede crear una lista que se vea así:
y usa tu prueba de mapa original:
Una forma de hacerlo sería crear explícitamente la lista de antemano:
Alternativamente, puede tirar del
itertools
módulo.itertools
contiene muchas funciones inteligentes que lo ayudan a realizar una programación de evaluación perezosa de estilo funcional en python. En este caso, queremositertools.repeat
, que generará su argumento de forma indefinida a medida que lo repita. Este último hecho significa que si haces:obtendrá una salida infinita, ya que
map()
continúa mientras uno de los argumentos siga produciendo. Sin embargo,itertools.imap
es igualmap()
, pero se detiene tan pronto como se detiene el iterativo más corto.Espero que esto ayude :-)
(*) Es un poco diferente en python 3.0. Allí, map () esencialmente devuelve una expresión generadora.
fuente
itertools.imap(f, sequence1, sequence2)
realmente es equivalente a[f(x1, x2) for x1, x2 in zip(sequence1, sequence2)]
?list(itertools.imap(f, sequence1, sequence2))
Aquí está la solución que estás buscando:
Recomiendo usar una comprensión de la lista (la
[(x, bars) for x in foos]
parte) sobre el uso del mapa, ya que evita la sobrecarga de una llamada a la función en cada iteración (que puede ser muy significativo). Si solo lo va a usar en un bucle for, obtendrá mejores velocidades utilizando un generador de comprensión:La diferencia es que la comprensión del generador está perezosamente cargada .
ACTUALIZACIÓN En respuesta a este comentario:
Supongo que este es un punto válido. Hay dos soluciones a esto en las que puedo pensar. El más eficiente es probablemente algo como esto:
Dado que las tuplas son inmutables, esto evitará que las barras se modifiquen a través de los resultados de esta comprensión de la lista (o comprensión del generador si sigue esa ruta). Si realmente necesita modificar todos y cada uno de los resultados, puede hacer esto:
Sin embargo, esto puede ser un poco costoso tanto en términos de uso de memoria como de velocidad, por lo que lo recomendaría a menos que realmente necesite agregar a cada uno de ellos.
fuente
La programación funcional se trata de crear código libre de efectos secundarios.
map es una abstracción de transformación de lista funcional. Lo usas para tomar una secuencia de algo y convertirlo en una secuencia de otra cosa.
Estás intentando usarlo como un iterador. No hagas eso. :)
Aquí hay un ejemplo de cómo puede usar el mapa para crear la lista que desea. Hay soluciones más cortas (solo usaría comprensiones), pero esto lo ayudará a comprender qué mapa funciona un poco mejor:
Tenga en cuenta que en este punto, solo ha realizado una manipulación de datos. Ahora puedes imprimirlo:
- No estoy seguro de lo que quieres decir con "sin bucles". fp no se trata de evitar bucles (no puede examinar cada elemento de una lista sin visitar cada uno). Se trata de evitar los efectos secundarios, por lo tanto, escribir menos errores.
fuente
fuente
fuente
Aquí hay una descripción general de los parámetros de la
map(function, *sequences)
función:function
es el nombre de tu función.sequences
es cualquier número de secuencias, que generalmente son listas o tuplas.map
iterará sobre ellos simultáneamente y dará los valores actuales afunction
. Es por eso que el número de secuencias debería ser igual al número de parámetros de su función.Parece que estás intentando iterar para algunos de
function
los parámetros pero mantener otros constantes, y desafortunadamentemap
no es compatible con eso. Encontré una vieja propuesta para agregar dicha característica a Python, pero la construcción del mapa es tan limpia y bien establecida que dudo que alguna vez se implemente algo así.Utilice una solución alternativa como las variables globales o comprensiones de listas, como lo han sugerido otros.
fuente
¿Esto lo haría?
fuente
bar
implica que está recibiendo un valor iterado, cuando realmente desea la lista completa.Qué tal esto:
fuente