2009-08-20 24 views
9

Tengo el siguiente código que utilizo para mapear una lista anidada en Python para producir una lista con la misma estructura.¿Asignación de una lista anidada con List Comprehension en Python?

>>> nested_list = [['Hello', 'World'], ['Goodbye', 'World']] 
>>> [map(str.upper, x) for x in nested_list] 
[['HELLO', 'WORLD'], ['GOODBYE', 'WORLD']] 

¿Se puede hacer esto con la comprensión de la lista solo (sin utilizar la función de mapa)?

Respuesta

12

Para listas anidadas puede utilizar listas por comprensión anidados:

nested_list = [[s.upper() for s in xs] for xs in nested_list] 

Personalmente encuentro map ser más limpio en esta situación, a pesar de que casi siempre prefiero listas por comprensión. Entonces, realmente es su decisión, ya que cualquiera funcionará.

+0

Ah, por supuesto. Debo estar más cansado de lo normal. – kjfletch

+0

en el mapa py3k requiere que se le aplique una lista. – SilentGhost

3

El mapa es sin duda una forma mucho más limpia de hacer lo que quiera. Sin embargo, puede anidar las listas de comprensión, ¿tal vez eso es lo que está buscando?

[[ix.upper() for ix in x] for x in nested_list] 
+0

Sí, puede ser más limpio usando el mapa pero me gustaría usar un generador. – kjfletch

0

Otros críticos han dado la respuesta, pero siempre que estoy teniendo problemas para envolver mi cabeza alrededor de una construcción funcional, que tragarme mi orgullo y lo dicen claramente escritura a mano con los métodos y/u objetos de forma explícita no óptimas. Usted dijo que quería terminar con un generador, así que:

for xs in n_l: 
    def doUpper(l): 
     for x in l: 
      yield x.upper() 
    yield doUpper(xs) 

for xs in n_l: 
    yield (x.upper() for x in xs) 

((x.upper() for x in xs) for xs in n_l) 

A veces es más limpio para mantener una de las versiones longhand. Para mí, mapear y reducir a veces lo hace más obvio, pero los modismos de Python pueden ser más obvios para otros.

2

Recuerde que el Zen de Python:.

En general, hay más de una - y probablemente varias - maneras obvias para hacerlo **

** Nota: Editado Para precisión.

De todos modos, prefiero el mapa.

from functools import partial 
nested_list = map(partial(map, str.upper), nested_list) 
+0

Wow. Aparentemente mi pequeño chiste sobre el Zen de Python realmente lastimó los sentimientos de alguien (y por lo tanto el voto negativo). ¡Ilumínate, gente! (FWIW, soy 100% sincero sobre el uso de 'map' en este caso) –

+1

" Debería haber [...] ", +1 para decir la verdad x-) – Edouard

1

Aquí es solución para lista anidada que tiene una profundidad arbitraria:

def map_nlist(nlist=nlist,fun=lambda x: x*2): 
    new_list=[] 
    for i in range(len(nlist)): 
     if isinstance(nlist[i],list): 
      new_list += [map_nlist(nlist[i],fun)] 
     else: 
      new_list += [fun(nlist[i])] 
    return new_list 

desea mayúsculas todo lo que un elemento de lista, sólo tiene que escribir

In [26]: nested_list = [['Hello', 'World'], ['Goodbye', [['World']]]] 
In [27]: map_nlist(nested_list,fun=str.upper) 
Out[27]: [['HELLO', 'WORLD'], ['GOODBYE', [['WORLD']]]] 

Y más importante, esta función recursiva puede hacer más que esto!

Soy nuevo en python, no dude en discutirlo!

+0

Use' append' en lugar de '+ =' , para evitar volver a crear una nueva lista para cada elemento. –

+0

@IoannisFilippidis Filippidis Hola, gracias por responder, pero ¿pueden darme más detalles sobre el problema con + =? No entiendo muy bien la diferencia ... (mucho tiempo sin usar python ...) – freeyoung

+1

Let 'a = list()'. Con 'a.append (0)' la misma instancia 'list' se extiende con un elemento más. Por el contrario, 'a + = [0]' crea una nueva lista '[0]' que luego se descarta de la memoria. Corrección a mi comentario anterior: pensé que '__iadd__' funcionaba como' __add__', pero usar 'id' reveló que no. Se pueden encontrar más detalles [aquí] (http://stackoverflow.com/questions/9766387/different-behaviour-for-list-iadd-and-list-add). –