Saltar al contenido principal

Operaciones con funciones anónimas

En la programación funcional las funciones pueden ser pasadas como argumentos a otras funciones, devueltas como valores de otras funciones o asignadas a variables. Esto último ya lo vimos en las expresiones lambda.

En este apartado veremos cómo pasar funciones a otras funciones para manipular listas. Todas las funciones que vamos a ver no modifican las listas originales.

Mapear una lista con map()

Si queremos realizar una operación sobre cada elemento de una lista podemos utilizar la función map(). Su sintaxis es la siguiente:

map(función, lista)

Esta devuelve un objeto map, por lo que es necesario pasarlo a una lista utilizando la función list(). El objeto map es un iterador que aplica una función especificada a cada elemento de un iterable, por lo que si deseamos obtener una lista, debemos crear una lista a partir de este iterador.

Si la función solo tiene una expresión, podemos utilizar una expresión lambda. En este caso solo tenemos un parámetro, que se puede expresar con cualquier nombre de parámetro, pero generalmente se utiliza la variable x.

La función map a cada elemento de la lista, le aplica la función que se pasa por parámetro. Es decir, el parámetro de la función lambda es cada uno de los elementos de la lista.

El objeto map que devuelve la función con el mismo nombre, contendrá los resultados de todas las ejecuciones de la función que se pasa por parámetro.

Por ejemplo, queremos multiplicar por 2 los elementos de una lista de números utilizando la función map():

numeros = [1, 2, 3]
objeto_map = map(lambda x: x*2 , numeros) # Obtenemos el objeto de tipo map
nuevos_numeros = list(objeto_map) # Pasamos el objeto tipo map a una lista


numeros = list(map(lambda x: x*2 , numeros)) # De este modo sobrescribimos la lista original en una sola línea

Filtrar elementos de una lista con filter()

Para ello podemos utilizar la función filter(). La sintaxis es igual que la función map() y devuelve también un objeto iterador (filter).

En este caso, la expresión lambda se aplica sobre cada elemento de la lista. Si el resultado de esta función devuelve True el elemento estará en el objeto filter, y si devuelve False no estará. En este ejemplo filtramos solo los números pares:

numeros = [1, 2, 3, 4]
pares = list(filter(lambda x: x%2 == 0 , numeros)) # De este modo tenemos una lista solo con los números pares

Ordenar elementos de una lista con sorted()

La función sorted() se utiliza para ordenar listas. Toma como argumento una lista. En este caso sí que devuelve una lista.

Como parámetros opcionales tiene el parámetro key. Con este parámetro se puede indicar mediante una función lambda la clave por la que se va a ordenar cada elemento.

Además tiene el parámetro opcional reverse que recibe un booleano. Esto sirve para indicar si el orden debe ser inverso o no.

# Lista de números
numeros = [5, 2, 8, 1, 9, 3]

# Ordenar la lista de números
numeros_ordenados = sorted(numeros)

# Ordenar la lista de números de forma descendente
numeros_ordenados_desc = sorted(numeros, reverse=True)

# Lista de tuplas
tuplas = [(1, 5), (3, 2), (7, 8), (6, 4)]

# Ordena la lista de tuplas por el segundo elemento de la tupla
tuplas_ordenadas = sorted(tuplas, key=lambda x: x[1])

print(tuplas_ordenadas) # Salida: [(3, 2), (6, 4), (1, 5), (7, 8)]

Función groupby()

La función groupby de itertools permite agrupar elementos de una lista en función de una clave especificada mediante el parámetro key.

Devuelve un iterador de tuplas clave-valor.

from itertools import groupby

datos = [["a", 1], ["a", 2], ["b", 3], ["b", 4], ["a", 5]]

# Agrupamos por clave
grupos = groupby(datos, key=lambda x: x[0])

for clave, grupo in grupos:
print(clave, list(grupo))
# Salida:
# a [('a', 1), ('a', 2)]
# b [('b', 3), ('b', 4)]
# a [('a', 5)]

Nota importante: Los datos deben estar ordenados previamente por la clave de agrupación para que groupby funcione correctamente.

Función reduce()

La función reduce() en Python pertenece al módulo functools y se usa para aplicar una función acumulativa sobre una lista, reduciendo sus elementos a un único valor.

from functools import reduce

reduce(función, iterable, valor_inicial)
  • función: una función que toma dos argumentos y devuelve un valor combinado. Generalmente utilizamos una función lambda.
  • iterable: la secuencia de datos sobre la que se aplicará reduce().
  • valor_inicial (opcional): un valor inicial para el cálculo.

En este caso sumamos todos los elementos de una lista:

from functools import reduce

numeros = [1, 2, 3, 4, 5]
suma = reduce(lambda x, y: x + y, numeros)

print(suma) # 15 (1+2+3+4+5)

La función reduce() realiza las siguientes operaciones:

  • (1 + 2) → 3
  • (3 + 3) → 6
  • (6 + 4) → 10
  • (10 + 5) → 15

Si agregamos un valor inicial, reduce() comienza con ese valor:

numeros = [1, 2, 3]
suma = reduce(lambda x, y: x + y, numeros, 10)

print(suma) # 16 (10+1+2+3)

Función zip()

La función zip() en Python se usa para combinar varios iterables (listas) en tuplas, creando un iterador de pares (o grupos) de elementos de los iterables dados.

zip(iterable1, iterable2, ...)
  1. Toma varios iterables.
  2. Agrupa sus elementos por posición (1º con 1º, 2º con 2º...).
  3. Devuelve un iterador de tuplas con los elementos agrupados.

Podemos combinar dos listas:

nombres = ["Ana", "Bruno", "Carlos"]
edades = [25, 30, 22]

combinado = zip(nombres, edades)
print(list(combinado)) # [('Ana', 25), ('Bruno', 30), ('Carlos', 22)]

Si un iterable es más corto que otro, zip() termina cuando se agota el más corto.

Función all()

all() devuelve True si todos los elementos resultantes son True.

Comprobar si todos los números son positivos:

numeros = [1, 2, 3, 4]
print(all(x > 0 for x in numeros)) # True

numeros2 = [1, -2, 3, 4]
print(all(x > 0 for x in numeros2)) # False (porque hay un -2)

all([]) devuelve True porque no hay elementos que sean False.

Función any()

any() devuelve True si al menos uno de los elementos es True.

Comprobar si hay algún número positivo:

numeros = [-1, -2, 3, -4]
print(any(x > 0 for x in numeros)) # True (porque hay un 3)

numeros2 = [-1, -2, -3, -4]
print(any(x > 0 for x in numeros2)) # False (ninguno es positivo)

any([]) devuelve False porque no hay elementos que sean True.