2013-08-31 8 views
44

ho due liste, come di seguitoCome inquadrare due cicli for a list comprehension pitone

tags = [u'man', u'you', u'are', u'awesome'] 
entries = [[u'man', u'thats'],[ u'right',u'awesome']] 

Voglio estrarre le voci dalla entries quando sono in tags:

result = [] 

for tag in tags: 
    for entry in entries: 
     if tag in entry: 
      result.extend(entry) 

Come posso scrivere i due anelli come una comprensione di una linea singola?

+2

Usa 'itertools.chain' se volete un elenco appiattito:' lista (catena .from_iterable (voce per tag nei tag per l'immissione nelle voci se tag in entrata)) ' –

risposta

57

Questo dovrebbe farlo:

[entry for tag in tags for entry in entries if tag in entry] 
3

Il LC appropriata sarebbe

[entry for tag in tags for entry in entries if tag in entry] 

L'ordine delle anse della LC è simile a quelle in cicli annidati, il if andare alla fine e le espressioni condizionali vanno in principio, qualcosa come

[a if a else b for a in sequence] 

vedere la demo -

>>> tags = [u'man', u'you', u'are', u'awesome'] 
>>> entries = [[u'man', u'thats'],[ u'right',u'awesome']] 
>>> [entry for tag in tags for entry in entries if tag in entry] 
[[u'man', u'thats'], [u'right', u'awesome']] 
>>> result = [] 
    for tag in tags: 
     for entry in entries: 
      if tag in entry: 
       result.append(entry) 


>>> result 
[[u'man', u'thats'], [u'right', u'awesome']] 

EDIT - Poiché è necessario che il risultato sia appiattito, è possibile utilizzare un elenco simile per comprendere e quindi appiattire i risultati.

>>> result = [entry for tag in tags for entry in entries if tag in entry] 
>>> from itertools import chain 
>>> list(chain.from_iterable(result)) 
[u'man', u'thats', u'right', u'awesome'] 

L'aggiunta di questo insieme, si può solo fare

>>> list(chain.from_iterable(entry for tag in tags for entry in entries if tag in entry)) 
[u'man', u'thats', u'right', u'awesome'] 

si utilizza un generatore di espressione qui invece di una lista di comprensione. (Corrisponde perfettamente il limite di 79 caratteri troppo (senza la chiamata list))

76

Il modo migliore per ricordare questo è che l'ordine del ciclo for all'interno di lista si basa nell'ordine in cui appaiono nell'approccio ad anello tradizionale. La maggior parte del loop esterno viene prima, quindi i loop interni successivamente.

Così, l'equivalente di lista sarebbe:

[entry for tag in tags for entry in entries if tag in entry] 

In generale, if-else dichiarazione viene prima del primo ciclo, e se hai solo un if dichiarazione, si arriverà alla fine. Per esempio, se si desidera aggiungere una lista vuota, se tag non è in ingresso, si dovrebbe fare in questo modo:

[entry if tag in entry else [] for tag in tags for entry in entries]