¿Cómo aplicar una función a cada lista secundaria de una lista en python?

Digamos que tengo una lista como esta:

list_of_lists = [['how to apply'],['a function'],['to each list?']] 

Y tengo una función, digamos que quiero aplicar la función F a cada sublista de la función F , puedo calcular un puntaje en dos listas. ¿Cómo se puede aplicar esta función F a cada lista de list_of_lists y devolver cada puntaje en una nueva lista como esta?

 new_list = [score_1, score_2, score_3] 

Probé con la función de map lo siguiente:

 map(F, list_of_lists).append(new_list) 

Puedes usar el map incorporado para hacer esto.

Entonces, si la función que quieres aplicar es len , harías:

 >>> list_of_lists = [['how to apply'],['a function'],['to each list?']] >>> map(len, list_of_lists) [1, 1, 1] 

En Python3 , lo anterior devuelve un iterador de mapa, por lo que necesitará una llamada de list explícita:

 >>> map(len, list_of_lists)  >>> list(map(len, list_of_lists)) [1, 1, 1] 

Si está buscando escribir algún código para esto que tenga que ser compatible tanto con Python2 como con Python3, la comprensión de la lista es el camino a seguir. Algo como:

 [apply_function(item) for item in list_of_lists] 

trabajará en Python 2 y 3 sin ningún cambio.

Sin embargo, si su entrada list_of_lists es enorme, el uso del map en Python3 tendría más sentido porque el iterador será mucho más rápido.

Qué tal si

 [ F(x) for x in list_of_lists ] 

que iterará sobre list_of_lists, llame a F con cada sublista como argumento, luego genere una lista de los resultados.

Si desea utilizar los sublistas como todos los argumentos de F , podría hacerlo de forma ligeramente diferente a

 [ F(*x) for x in list_of_lists ] 

Puedes usar una lista de comprensión, como esta

 [function_to_be_done(item) for item in list_of_lists] 

Por ejemplo,

 >>> list_of_lists = [['how to apply'],['a function'],['to each list?']] >>> [len(item) for item in list_of_lists] [1, 1, 1] 

Nota: Aunque las comprensiones de listas parecen una forma de aplicar una función a todos los elementos, su propósito principal es construir una nueva lista. Entonces, si no desea construir una nueva lista, simplemente repita con for loop y llame a la función.


Aparte de eso, puedes usar la función de map en Python 2.7, para aplicar una función a todos los elementos y construir una lista. Por ejemplo,

 >>> list_of_lists = [['how to apply'],['a function'],['to each list?']] >>> map(len, list_of_lists) [1, 1, 1] 

Pero, map devuelve un objeto iterador de mapa en Python 3.x. Por lo tanto, necesitas convertirlo explícitamente en una lista, como esta

 >>> list_of_lists = [['how to apply'],['a function'],['to each list?']] >>> map(len, list_of_lists)  >>> list(map(len, list_of_lists)) [1, 1, 1] 

Es posible que desee leer sobre lo que Guido piensa acerca del map en esta publicación .

Básicamente, el map le exigirá con mayor frecuencia que cree una nueva función (en su mayoría, la gente crea una función lambda ). Pero en muchos casos, la comprensión de la lista evita eso.

Algo que funciona en listas anidadas arbitrariamente, por ejemplo, [[1,2], [[5]], [7, [8, [9,11]]]]

 def apply_f(a,f): if isinstance(a,list): return map(lambda t:apply_f(t,f), a) else: return f(a) 

Aquí hay un ejemplo de correr esto:

 >>> ll=[[1,2],[[5]],[7,[8,[9,11]]]] >>> apply_f(ll,lambda t:t**2) [[1, 4], [[25]], [49, [64, [81, 121]]]] 

y aquí es cómo hacer lo mismo solo en niveles seleccionados:

 def apply_f(a,f,depth,levels): if isinstance(a,list): return map(lambda t:apply_f(t,f,depth+1,levels), a) else: if depth in levels: return f(a) else: return a 

consiguiendo por ejemplo

 >>> apply_f(ll,lambda t:t**2, 0, [2,4]) [[1, 4], [[5]], [49, [8, [81, 121]]]] 

Hay algunas optimizaciones que hacer aquí, evitando pasar f y los levels (haciendo de la función recursiva una función interna en una envoltura, de modo que pueda usar f y los levels desde el scope externo), pero eso es algo menor. (Tenga en cuenta que esto es Python 2, para Python 3 necesita reemplazar el map con otra cosa).


Para una entrada más genérica, lo siguiente haría el truco:

 def apply_f(a,f): try: return(f(a)) except: return map(lambda t:apply_f(t,f), a) 

Así que ahora también el siguiente tipo de trabajos:

 >> apply_f([(1,2),[[5]],[7,(8,[9,11])]],lambda t:t**2) [[1, 4], [[25]], [49, [64, [81, 121]]]] 

(Las cosas se reescriben un poco, ya que map() siempre produce listas …)

Mapa es tu amigo! map toma una función y una iterable (lista, por ejemplo) y aplica la función en cada elemento de la lista.

 map(len, [['how to apply'],['a function'],['to each list?']]) 

Salida

 [1, 1, 1] 

Si desea hacer un cálculo más detallado de los elementos de la lista secundaria, puede anidar el mapa:

 map(lambda x: map(lambda y: y + 1, x), [[1], [1, 2], [1, 2, 3]]) 

Salida

 [[2], [2, 3], [2, 3, 4]] 

Otro enfoque posible (también desde la progtwigción funcional) son las listas de comprensión. La comprensión de listas es una forma de construir una lista desde iterable en Python. La syntax es [element for element in iterable] . Cualquier cálculo se puede hacer en el elemento, por lo que

 [f(element) for element in iterable] 

significa que la lista resultante será una lista de elementos, donde cada elemento es el resultado de la función f. Al igual que en el mapa, la comprensión de la lista se puede anidar aún más, dando como resultado una aplicación de función de elemento nested.

 [element + 1 for element in el] for el in [[1], [1, 2], [1, 2, 3]]] 

Salida

 [[2], [2, 3], [2, 3, 4]]