2009-08-20 4 views
9

Ho il seguente codice che uso per mappare un elenco annidato in Python per produrre un elenco con la stessa struttura.Mappare una lista annidata con Comprensione delle liste in Python?

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

questo può essere fatto con la lista solo di comprensione (senza utilizzare la funzione di mappa)?

risposta

12

Per le liste nidificate è possibile utilizzare list comprehension nidificate:

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

Personalmente trovo map ad essere più pulita in questa situazione, anche se io preferisco quasi sempre list comprehension. Quindi è davvero la tua chiamata, dal momento che entrambi funzioneranno.

+0

Ah, naturalmente. Devo essere più stanco del solito. – kjfletch

+0

nella mappa py3k richiede l'applicazione di un elenco. – SilentGhost

3

La mappa è sicuramente un modo molto più pulito di fare quello che vuoi. Puoi annidare le comprensioni delle liste, forse è quello che cerchi?

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

Sì, potrebbe essere più pulito utilizzando la mappa ma mi piacerebbe utilizzare un generatore. – kjfletch

0

altri utenti hanno dato la risposta, ma ogni volta che sto avendo problemi confezionamento mia testa intorno a un costrutto funzionale, ho ingoiare il mio orgoglio e magia fuori longhand con metodi e/o gli oggetti in modo esplicito non ottimali. Hai detto che volevi finire con un generatore, in modo da:

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 volte è più pulita per mantenere una delle versioni esteso. Per me, mappare e ridurre a volte renderlo più ovvio, ma gli idiomi di Python potrebbero essere più ovvi per gli altri.

2

Ricordate la Zen di Python:.

V'è in generale più di uno - e probabilmente diversi - modi ovvi per farlo **

** Nota: A cura per precisione.

In ogni caso, preferisco la mappa.

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

Wow. Apparentemente la mia piccola battuta sullo Zen di Python ferisce davvero i sentimenti di qualcuno (e quindi il downvote). Alleggeriti, gente! (FWIW, sono sincero al 100% sull'uso di 'map' in questa istanza.) –

+1

" Ci dovrebbe essere [...] ", +1 per dire la verità x-) – Edouard

1

Ecco soluzione per lista annidata che ha profondità 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 

si desidera maiuscolo tutto quello che lista degli elementi, basta digitare

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

E più importante, questa funzione ricorsiva può fare più di questo!

Sono nuovo di Python, sentitevi liberi di discutere!

+0

Usa' append' invece di '+ =' , per evitare di ricreare un nuovo elenco per ciascun articolo. –

+0

@IoannisFilippidis Filippidis Hey, grazie per la risposta, ma puoi fornirmi maggiori dettagli sul problema con + =? Non capisco la differenza ... (molto tempo non uso python ..) – freeyoung

+1

Lasciamo 'a = list()'. Con 'a.append (0)' la stessa istanza 'list' è estesa con un altro elemento. Al contrario, 'a + = [0]' crea una nuova lista '[0]' che viene quindi eliminata dalla memoria. Correzione al mio precedente commento: pensavo che '__iadd__' funzionasse come' __add__', ma usando 'id' ha rivelato che non lo era. Maggiori dettagli possono essere trovati [qui] (http://stackoverflow.com/questions/9766387/different-behaviour-for-list-iadd-and-list-add). –