Como enquadrar dois loops for em python de compreensão de lista

101

Eu tenho duas listas como abaixo

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

Quero extrair entradas de entriesquando elas estiverem em tags:

result = []

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

Como posso escrever os dois loops como uma compreensão de lista de uma única linha?

Shiva Krishna Bavandla
fonte
3
Use itertools.chainse quiser uma lista nivelada:list(chain.from_iterable(entry for tag in tags for entry in entries if tag in entry))
Ashwini Chaudhary

Respostas:

135

Isso deve servir:

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

fonte
157

A melhor maneira de lembrar isso é que a ordem do loop for dentro da compreensão da lista é baseada na ordem em que eles aparecem na abordagem de loop tradicional. A maioria dos loops externos vem primeiro e, em seguida, os loops internos subsequentemente.

Portanto, a compreensão de lista equivalente seria:

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

Em geral, a if-elseinstrução vem antes do primeiro loop for e, se você tiver apenas uma ifinstrução, ela virá no final. Por exemplo, se você gostaria de adicionar uma lista vazia, se tagnão estiver na entrada, você faria assim:

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

O LC apropriado seria

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

A ordem dos loops no LC é semelhante à dos loops aninhados, as instruções if vão para o final e as expressões condicionais vão para o início, algo como

[a if a else b for a in sequence]

Veja a demonstração -

>>> 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 - Como você precisa que o resultado seja nivelado, você pode usar uma compreensão de lista semelhante e, em seguida, nivelar os 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']

Somando isso, você poderia apenas fazer

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

Você usa uma expressão geradora aqui em vez de uma compreensão de lista. (Corresponde perfeitamente ao limite de 79 caracteres também (sem a listchamada))

Sukrit Kalra
fonte
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)

Resultado:

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

Na compreensão, a iteração de listas aninhadas deve seguir a mesma ordem que os loops for imbricados equivalentes.

Para entender, vamos dar um exemplo simples da PNL. Você deseja criar uma lista de todas as palavras de uma lista de frases em que cada frase é uma lista de palavras.

>>> 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 remover as palavras repetidas, você pode usar um conjunto {} em vez de uma 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']

ou aplique list(set(all_words))

>>> all_unique_words = list(set(all_words))
['.', 'dog', 'the', 'chases', 'barks', 'mouse', 'The', 'cat']
Claude COULOMBE
fonte
0
return=[entry for tag in tags for entry in entries if tag in entry for entry in entry]
TARUN KUMAR Singh
fonte
6
Olá, bem-vindo ao Stack Overflow! Por favor, poste uma explicação e não apenas um código.
Evelyn
1
Olá! Embora este código possa resolver a questão, incluir uma explicação de como e por que isso resolve o problema realmente ajudaria a melhorar a qualidade da sua postagem e provavelmente resultaria em mais votos positivos. Lembre-se de que você está respondendo às perguntas dos leitores no futuro, não apenas da pessoa que está perguntando agora. Por favor edite sua resposta para adicionar explicações e dar uma indicação do que limitações e premissas se aplicam.
Brian