Cómo enmarcar dos bucles for en Python de comprensión de listas

101

Tengo dos listas como abajo

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

Quiero extraer entradas de entriescuando están en tags:

result = []

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

¿Cómo puedo escribir los dos bucles como una comprensión de lista de una sola línea?

Shiva Krishna Bavandla
fuente
3
Úselo itertools.chainsi desea una lista plana:list(chain.from_iterable(entry for tag in tags for entry in entries if tag in entry))
Ashwini Chaudhary

Respuestas:

135

Esto debería hacerlo:

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

fuente
157

La mejor manera de recordar esto es que el orden del bucle for dentro de la lista de comprensión se basa en el orden en el que aparecen en el enfoque de bucle tradicional. La mayoría de los bucles externos vienen primero y luego los bucles internos posteriormente.

Entonces, la comprensión de la lista equivalente sería:

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

En general, la if-elseinstrucción viene antes del primer ciclo for, y si solo tiene una ifinstrucción, aparecerá al final. Por ejemplo, si desea agregar una lista vacía, si tagno está en la entrada, lo haría así:

[entry if tag in entry else [] for tag in tags for entry in entries]
Rohit Jain
fuente
6

El LC apropiado sería

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

El orden de los bucles en el LC es similar al de los bucles anidados, las instrucciones if van al final y las expresiones condicionales van al principio, algo así como

[a if a else b for a in sequence]

Ver la demostración -

>>> 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']]

EDITAR : dado que necesita que el resultado se acople, puede usar una lista de comprensión similar y luego acoplar los resultados.

>>> 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']

Sumando esto, podrías hacer

>>> 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']

Aquí usa una expresión generadora en lugar de una lista de comprensión. (También coincide perfectamente con el límite de 79 caracteres (sin la listllamada))

Sukrit Kalra
fuente
2
tags = [u'man', u'you', u'are', u'awesome']
entries = [[u'man', u'thats'],[ u'right',u'awesome']]

result = []
[result.extend(entry) for tag in tags for entry in entries if tag in entry]

print(result)

Salida:

['man', 'thats', 'right', 'awesome']
Raghav Gupta
fuente
0

En comprensión, la iteración de listas anidadas debe seguir el mismo orden que los bucles for imbricados equivalentes.

Para entenderlo, tomaremos un ejemplo sencillo de PNL. Desea crear una lista de todas las palabras a partir de una lista de oraciones donde cada oración es una lista de palabras.

>>> list_of_sentences = [['The','cat','chases', 'the', 'mouse','.'],['The','dog','barks','.']]
>>> all_words = [word for sentence in list_of_sentences for word in sentence]
>>> all_words
['The', 'cat', 'chases', 'the', 'mouse', '.', 'The', 'dog', 'barks', '.']

Para eliminar las palabras repetidas, puede utilizar un conjunto {} en lugar de una lista []

>>> all_unique_words = list({word for sentence in list_of_sentences for word in sentence}]
>>> all_unique_words
['.', 'dog', 'the', 'chase', 'barks', 'mouse', 'The', 'cat']

o aplicar list(set(all_words))

>>> all_unique_words = list(set(all_words))
['.', 'dog', 'the', 'chases', 'barks', 'mouse', 'The', 'cat']
Claude COULOMBE
fuente
0
return=[entry for tag in tags for entry in entries if tag in entry for entry in entry]
TARUN KUMAR Singh
fuente
6
Hola y bienvenido a Stack Overflow. Publique una explicación y no solo el código.
Evelyn
1
¡Hola! Si bien este código puede resolver la pregunta, incluir una explicación de cómo y por qué esto resuelve el problema realmente ayudaría a mejorar la calidad de su publicación y probablemente resultaría en más votos a favor. Recuerde que está respondiendo la pregunta a los lectores en el futuro, no solo a la persona que pregunta ahora. Por favor, editar su respuesta para agregar explicaciones y dar una indicación de lo que se aplican limitaciones y supuestos.
Brian