Compreensão de lista de uma linha: variantes if-else


178

É mais sobre sintaxe de compreensão da lista python. Eu tenho uma compreensão de lista que produz lista de números ímpares de um determinado intervalo:

[x for x in range(1, 10) if x % 2]

Isso cria um filtro - eu tenho uma lista de fontes, onde removo números pares ( if x % 2). Eu gostaria de usar algo como se-então-outro aqui. O código a seguir falha:

>>> [x for x in range(1, 10) if x % 2 else x * 100]
  File "<stdin>", line 1
    [x for x in range(1, 10) if x % 2 else x * 100]
                                         ^
SyntaxError: invalid syntax

Há uma expressão python como if-else:

1 if 0 is 0 else 3

Como usá-lo dentro de uma compreensão de lista?


1
Veja o que vale, você tem uma "compreensão da lista", não um gerador. A sintaxe final é a mesma, exceto que os geradores usam em ()vez de [].
mgilson


2
Demorei um pouco para entender por que os números pares foram if x % 2 eliminados (em vez de mantê-los) - é porque quando xé que a x % 2expressão resulta 0, que, por sua vez, avalia como False, enquanto qualquer um intexceto 0avalia True.

Respostas:


328

x if y else zé a sintaxe da expressão que você está retornando para cada elemento. Assim você precisa:

[ x if x%2 else x*100 for x in range(1, 10) ]

A confusão surge do fato de você estar usando um filtro no primeiro exemplo, mas não no segundo. No segundo exemplo, você está mapeando apenas cada valor para outro, usando uma expressão de operador ternário.

Com um filtro, você precisa:

[ EXP for x in seq if COND ]

Sem um filtro, você precisa:

[ EXP for x in seq ]

e no seu segundo exemplo, a expressão é "complexa", que envolve um if-else.


2
Eu tenho uma pergunta ... [x for x in range(1, 10) if x % 2]é a sintaxe correta. [x if x % 2 for x in range(1, 10)]- isto não é, mas [x if x%2 else x*100 for x in range(1, 10)]é novamente, sintaxe correta. Por quê?
ducin

@tkoomzaaskz em seu segundo exemplo, este não é um operador ternário se-mais (faltando o else), nem um filtro (uma vez que é na EXPparte da lista de compreensão)
shx2

3
@tkoomzaaskz Para esclarecer, note que você pode adicionar um segundo ifno final: [x if x%2 else x*100 for x in range(1, 10) if not x%3]O primeiro iffaz parte do operador ternário, o segundo iffaz parte da sintaxe de compreensão da lista. O todo x if x%2 else x*100é "no mesmo nível" como um simples 2*x, é a expressão a ser avaliada no lado esquerdo do for, quando a filtragem if not x%3já tiver ocorrido.
Zx81

Olá, uma declaração de uma linha seria mais eficiente do que fazê-la em duas linhas como for i in x:e depois no loop for if i == y:?
Alexis.Rolland

23
[x if x % 2 else x * 100 for x in range(1, 10) ]

12

Você também pode fazer isso com a compreensão da lista:

A=[[x*100, x][x % 2 != 0] for x in range(1,11)]
print A

1
Muito agradável. Uma fatia booleana. Obrigado, você me deu uma solução mais fácil de ler.

Também pode fazer duplo atribuir assim: A, B = [10,11] [a == 19], [1,14] [a == 20]
Stefan Gruenwald

10

Apenas mais uma solução, espero que alguém goste:

Usando: [Falso, Verdadeiro] [Expressão]

>>> map(lambda x: [x*100, x][x % 2 != 0], range(1,10))
[1, 200, 3, 400, 5, 600, 7, 800, 9]
>>>

3

Eu consegui fazer isso

>>> [x if x % 2 != 0 else x * 100 for x in range(1,10)]
    [1, 200, 3, 400, 5, 600, 7, 800, 9]
>>>
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.