map (), filter () y reduce () en Python con ejemplos

    Introducción

    los map(), filter() y reduce() Las funciones aportan un poco de programación funcional a Python. Las tres son funciones de conveniencia que se pueden reemplazar con listas comprensivas o bucles, pero brindan un enfoque más elegante y abreviado para algunos problemas.

    Antes de continuar, repasaremos algunas cosas con las que debería estar familiarizado antes de leer sobre los métodos mencionados anteriormente:

    ¿Qué es una función / método anónimo o lambda?

    Un método anónimo es un método sin nombre, es decir, no vinculado a un identificador como cuando definimos un método usando def method:.

    Nota: Aunque la mayoría de la gente usa los términos «función anónima» y «función lambda» indistintamente, no son lo mismo. Este error ocurre porque en la mayoría de los lenguajes de programación las lambdas son anónimas y todas las funciones anónimas son lambdas. Este también es el caso de Python. Por lo tanto, no profundizaremos en esta distinción en este artículo.

    ¿Cuál es la sintaxis de una función lambda (u operador lambda)?

    lambda arguments: expression
    

    Piense en lambdas como métodos de una línea sin nombre. Funcionan prácticamente igual que cualquier otro método en Python, por ejemplo:

    def add(x,y):
    	return x + y
    

    Puede traducirse a:

    lambda x, y: x + y
    

    Las lambdas difieren de los métodos normales de Python porque solo pueden tener una expresión, no pueden contener declaraciones y su tipo de retorno es un function objeto. Entonces, la línea de código anterior no devuelve exactamente el valor x + y pero la función que calcula x + y.

    ¿Por qué las lambdas son relevantes para map(), filter() y reduce()?

    Los tres de estos métodos esperan una function objeto como primer argumento. Esta function El objeto puede ser un método predefinido con un nombre (como def add(x,y)).

    Aunque, la mayoría de las veces, las funciones pasan a map(), filter()y reduce() son los que usaría solo una vez, por lo que a menudo no tiene sentido definir una función referenciable.

    Para evitar definir una nueva función para sus diferentes map()/filter()/reduce() necesidades: una solución más elegante sería utilizar una función breve, desechable y anónima que solo usará una vez y nunca más: una lambda.

    La función map ()

    los map() La función itera a través de todos los elementos en el iterable dado y ejecuta el function pasamos como argumento en cada uno de ellos.

    La sintaxis es:

    map(function, iterable(s))
    

    Podemos pasar tantos objetos iterables como queramos después de pasar el function queremos usar:

    # Without using lambdas
    def starts_with_A(s):
        return s[0] == "A"
    
    fruit = ["Apple", "Banana", "Pear", "Apricot", "Orange"]
    map_object = map(starts_with_A, fruit)
    
    print(list(map_object))
    

    Este código resultará en:

    [True, False, False, True, False]
    

    Como podemos ver, terminamos con una nueva lista donde la función starts_with_A() fue evaluado para cada uno de los elementos de la lista fruit. Los resultados de esta función se agregaron a la lista de forma secuencial.

    Una forma más bonita de hacer exactamente lo mismo es usando lambdas:

    fruit = ["Apple", "Banana", "Pear", "Apricot", "Orange"]
    map_object = map(lambda s: s[0] == "A", fruit)
    
    print(list(map_object))
    

    Obtenemos el mismo resultado:

    [True, False, False, True, False]
    

    Nota: Puede que hayas notado que hemos emitido map_object a una lista para imprimir el valor de cada elemento. Hicimos esto porque llamamos print() en una lista imprimirá los valores reales de los elementos. Vocación print() en map_object imprimiría las direcciones de memoria de los valores en su lugar.

    los map() función devuelve el map_object type, que es iterable y podríamos haber impreso los resultados de esta manera también:

    for value in map_object:
        print(value)
    

    Si quieres el map() función para devolver una lista en su lugar, puede simplemente convertirla al llamar a la función:

    result_list = list(map(lambda s: s[0] == "A", fruit))
    

    La función filter ()

    Similar a map(), filter() toma una function objeto y un iterable y crea una nueva lista.

    Como el nombre sugiere, filter() forma una nueva lista que contiene solo elementos que satisfacen una determinada condición, es decir, la function pasamos devoluciones True.

    La sintaxis es:

    filter(function, iterable(s))
    

    Usando el ejemplo anterior, podemos ver que la nueva lista solo contendrá elementos para los cuales el starts_with_A() devuelve la función True:

    # Without using lambdas
    def starts_with_A(s):
        return s[0] == "A"
    
    fruit = ["Apple", "Banana", "Pear", "Apricot", "Orange"]
    filter_object = filter(starts_with_A, fruit)
    
    print(list(filter_object))
    

    Ejecutar este código resultará en una lista más corta:

    ['Apple', 'Apricot']
    

    O reescrito usando una lambda:

    fruit = ["Apple", "Banana", "Pear", "Apricot", "Orange"]
    filter_object = filter(lambda s: s[0] == "A", fruit)
    
    print(list(filter_object))
    

    La impresión nos da el mismo resultado:

    ['Apple', 'Apricot']
    

    La función reduce ()

    reduce() funciona de manera diferente a map() y filter(). No devuelve una nueva lista basada en el function e iterable hemos pasado. En cambio, devuelve un solo valor.

    Además, en Python 3 reduce() ya no es una función incorporada, y se puede encontrar en el functools módulo.

    La sintaxis es:

    reduce(function, sequence[, initial])
    

    reduce() funciona llamando al function pasamos por los dos primeros elementos de la secuencia. El resultado devuelto por el function se usa en otra llamada a function junto con el siguiente (tercero en este caso), elemento.

    Este proceso se repite hasta que hayamos pasado por todos los elementos de la secuencia.

    El argumento opcional initial se utiliza, cuando está presente, al comienzo de este «bucle» con el primer elemento en la primera llamada a function. En cierto modo, el initial elemento es el elemento 0, antes del primero, cuando se proporciona.

    reduce() es un poco más difícil de entender que map() y filter(), así que veamos un ejemplo paso a paso:

    • Empezamos con una lista [2, 4, 7, 3] y pasar el add(x, y) función para reduce() junto a esta lista, sin un initial valor
    • reduce() llamadas add(2, 4)y add() devoluciones 6
    • reduce() llamadas add(6, 7) (resultado de la llamada anterior a add() y el siguiente elemento de la lista como parámetros), y add() devoluciones 13
    • reduce() llamadas add(13, 3)y add() devoluciones 16
    • Como no quedan más elementos en la secuencia, reduce() devoluciones 16

    La única diferencia, si hubiéramos dado un initial valor hubiera sido un paso adicional – 1.5. dónde reduce() Llamaría add(initial, 2) y usa ese valor de retorno en el paso 2.

    Sigamos adelante y usemos el reduce() función:

    from functools import reduce
    
    def add(x, y):
        return x + y
    
    list = [2, 4, 7, 3]
    print(reduce(add, list))
    

    Ejecutar este código produciría:

    16
    

    Nuevamente, esto podría escribirse usando lambdas:

    from functools import reduce
    
    list = [2, 4, 7, 3]
    print(reduce(lambda x, y: x + y, list))
    print("With an initial value: " + str(reduce(lambda x, y: x + y, list, 10)))
    

    Y el código resultaría en:

    16
    With an initial value: 26
    

    Conclusión

    Como se mencionó anteriormente, estas funciones son funciones de conveniencia. Están ahí para que pueda evitar escribir un código más engorroso, pero evite usar tanto ellos como las expresiones lambda demasiado.

    No fuerce estas herramientas porque «puede», ya que a menudo puede generar un código ilegible que es difícil de mantener. Úselos solo cuando esté absolutamente claro lo que está sucediendo tan pronto como observe la función o expresión lambda.

    Si te das cuenta de que estás luchando por encajar la lógica necesaria en una map() función, o una expresión lambda, es mucho mejor escribir un método for-loop / definido un poco más largo y evitar confusiones innecesarias más adelante.

    Etiquetas:

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *