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?


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]

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]

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))


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

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

0
return=[entry for tag in tags for entry in entries if tag in entry for entry in entry]

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.