map() y filter() en Python: cuándo usarlos y cuándo preferir comprehensions

map() y filter() son funciones de orden superior de Python 3 que devuelven iteradores. Son la forma funcional de transformar y filtrar iterables, aunque en la práctica la comunidad Python prefiere las list comprehensions en la mayoría de los casos.

map(): transformar cada elemento

# map(función, iterable) devuelve un iterador
numeros = [1, 2, 3, 4, 5]

# Con lambda
cuadrados = map(lambda x: x**2, numeros)
print(list(cuadrados))  # [1, 4, 9, 16, 25]

# Con función con nombre (más eficiente)
print(list(map(str, numeros)))   # ['1', '2', '3', '4', '5']
print(list(map(abs, [-1, 2, -3, 4])))  # [1, 2, 3, 4]

# map con múltiples iterables
a = [1, 2, 3]
b = [10, 20, 30]
print(list(map(lambda x, y: x + y, a, b)))  # [11, 22, 33]
# Se para en el más corto

filter(): filtrar según una condición

numeros = range(-5, 6)

# filter(función, iterable) — la función devuelve True/False
positivos = filter(lambda x: x > 0, numeros)
print(list(positivos))  # [1, 2, 3, 4, 5]

# filter(None, iterable) — elimina valores falsy
con_vacios = ["hola", "", None, "mundo", 0, "python"]
no_vacios  = list(filter(None, con_vacios))
print(no_vacios)  # ['hola', 'mundo', 'python']

map vs list comprehension

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

# Con map + lambda
cuadrados_map = list(map(lambda x: x**2, numeros))

# Con list comprehension (más legible, preferida en Python)
cuadrados_comp = [x**2 for x in numeros]

# Con map + función con nombre (comparable en legibilidad)
def cuadrado(x):
    return x**2
cuadrados_fn = list(map(cuadrado, numeros))

# Los tres producen el mismo resultado
# La PEP 8 y Guido van Rossum prefieren comprehensions cuando se usa lambda
# map() con función con nombre es aceptable y puede ser más rápido

filter vs list comprehension

numeros = range(20)

# filter + lambda
pares_filter = list(filter(lambda x: x % 2 == 0, numeros))

# comprehension (más clara)
pares_comp = [x for x in numeros if x % 2 == 0]

# Para condiciones complejas, la comprehension gana en legibilidad:
usuarios = [{"nombre": "Ana", "activo": True, "edad": 28},
            {"nombre": "Luis", "activo": False, "edad": 34}]

activos = [u for u in usuarios if u["activo"] and u["edad"] >= 18]
# vs
activos = list(filter(lambda u: u["activo"] and u["edad"] >= 18, usuarios))

Encadenar map y filter

datos = ["  Python  ", "", "  Rust  ", "  ", "Go"]

# Cadena de transformaciones con map y filter
# (sin crear listas intermedias — eficiente en memoria)
resultado = list(
    map(str.upper,
        filter(None,
               map(str.strip, datos)))
)
print(resultado)  # ['PYTHON', 'RUST', 'GO']

# La misma lógica con comprehension (más legible)
resultado = [s.strip().upper() for s in datos if s.strip()]

Cuándo usar map() o filter()

# USA map() cuando:
# - Ya tienes una función con nombre (sin necesidad de lambda)
# - Trabajas con múltiples iterables en paralelo
print(list(map(int, ["1", "2", "3"])))  # map + función existente

# USA filter() con None para eliminar falsy en una línea
print(list(filter(None, [0, 1, "", "ok", None, True])))

# USA comprehensions cuando la lógica involucra lambda
# o cuando la legibilidad importa más que un micro-benchmark

# En pipelines de datos con muchos pasos, map y filter
# evitan crear listas intermedias:
pipeline = filter(lambda x: x > 0, map(int, ["1", "-2", "3", "-4"]))
print(list(pipeline))  # [1, 3]

La guía de estilo de Python prefiere las comprehensions sobre map()/filter() con lambdas, pero map() con funciones ya definidas es perfectamente idiomático. La diferencia de rendimiento suele ser insignificante; elige en función de la legibilidad.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP