if / else em uma lista de compreensão

Respostas:

1461

Você pode fazer isso totalmente. É apenas uma questão de pedido:

[unicode(x.strip()) if x is not None else '' for x in row]

Em geral,

[f(x) if condition else g(x) for x in sequence]

E, para compreensão de lista ifapenas com condições,

[f(x) for x in sequence if condition]

Observe que, na verdade, isso usa uma construção de linguagem diferente, uma expressão condicional , que por si só não faz parte da sintaxe de compreensão , enquanto ifo que for…insegue faz parte das compreensões da lista e é usado para filtrar elementos da fonte iterável.


Expressões condicionais podem ser usadas em todos os tipos de situações em que você deseja escolher entre dois valores de expressão com base em alguma condição. Isso faz o mesmo que o operador ternário ?:que existe em outros idiomas . Por exemplo:

value = 123
print(value, 'is', 'even' if value % 2 == 0 else 'odd')
cutucar
fonte
141
Observe que a if / else aqui agora é a sintaxe do "operador ternário" e não a sintaxe de compreensão da lista.
Adam Vandenberg
8
É por isso que prefiro colocar o operador ternário entre colchetes, fica mais claro que é apenas uma expressão normal, não uma compreensão.
Jochen Ritzel
17
Portanto, o truque é "Na compactação de lista, eu escrevo se antes, então também tenho que adicionar outra parte". porque se o meu l = [ 2, 3, 4, 5]então [x if x % 2 == 0 for x in l]me dê erro enquanto [x if x % 2 == 0 else 200 for x in l]funciona. Sim, eu sei que para filtrar, devo escrever [ x for x in l if x % 2 == 0]. Desculpe pela incomodação. Obrigado pela sua resposta.
Grijesh Chauhan
5
Os documentos python mencionam o operador ternário . Observe que isso requer o else ou não funciona.
precisa saber é o seguinte
4
As compreensões da @Drewdin List não suportam quebra durante a iteração. Você terá que usar um loop normal então.
Poke
44

Mão única:

def change(f):
    if f is None:
        return unicode(f.strip())
    else:
        return ''

row = [change(x) for x in row]

Embora você tenha:

row = map(change, row)

Ou você pode usar um lambda inline.

Adam Vandenberg
fonte
13
Essa também é uma boa (talvez apenas) técnica a ser usada quando você precisa lidar com possíveis exceções da ifexpressão ou código em seu elsebloco de instruções. A resposta aceita é melhor para casos simples.
27510 martineau
37

Aqui está outro exemplo ilustrativo:

>>> print(", ".join(["ha" if i else "Ha" for i in range(3)]) + "!")
Ha, ha, ha!

Ele explora o fato de if iavaliar Falsepara 0e Truepara todos os outros valores gerados pela função range(). Portanto, a compreensão da lista é avaliada da seguinte forma:

>>> ["ha" if i else "Ha" for i in range(3)]
['Ha', 'ha', 'ha']
Bengt
fonte
37

O problema específico já foi resolvido nas respostas anteriores, portanto, abordarei a idéia geral de usar condicionais dentro da compreensão da lista.

Aqui está um exemplo que mostra como condicionais podem ser escritos dentro de uma compreensão de lista:

X = [1.5, 2.3, 4.4, 5.4, 'n', 1.5, 5.1, 'a']     # Original list

# Extract non-strings from X to new list
X_non_str = [el for el in X if not isinstance(el, str)]  # When using only 'if', put 'for' in the beginning

# Change all strings in X to 'b', preserve everything else as is
X_str_changed = ['b' if isinstance(el, str) else el for el in X]  # When using 'if' and 'else', put 'for' in the end

Observe que, na primeira compreensão da lista X_non_str, o pedido é:

expressão para item em iterável se condição

e na última lista de compreensão para X_str_changed, o pedido é:

expressão1 se condição outra expressão2 para o item em iterável

Eu sempre acho que é difícil lembrar que expresseion1 tem que ser antes de se e expressão2 tem que ser depois de outra coisa . Minha cabeça quer que ambos estejam antes ou depois.

Acho que foi projetado assim porque se assemelha à linguagem normal, por exemplo: "Quero ficar dentro de casa se chover, caso contrário , quero sair"

Em inglês simples, os dois tipos de compreensão de lista mencionados acima podem ser declarados como:

Com apenas if:

extract_apple para apple em box_of_apples se apple_is_ripe

e com if/else

mark_apple se apple_is_ripe outra leave_it_unmarked de maçã em box_of_apples

Tim Skov Jacobsen
fonte
7

As outras soluções são excelentes para um único if/ elseconstruo. No entanto, afirmações ternárias nas compreensões da lista são sem dúvida difíceis de ler.

O uso de uma função ajuda na legibilidade, mas é difícil estender ou adaptar essa solução em um fluxo de trabalho em que o mapeamento é uma entrada. Um dicionário pode aliviar essas preocupações:

row = [None, 'This', 'is', 'a', 'filler', 'test', 'string', None]

d = {None: '', 'filler': 'manipulated'}

res = [d.get(x, x) for x in row]

print(res)

['', 'This', 'is', 'a', 'manipulated', 'test', 'string', '']
jpp
fonte
1

Tem a ver com a forma como a compreensão da lista é realizada.

Lembre-se do seguinte:

[ expression for item in list if conditional ]

É equivalente a:

for item in list:
    if conditional:
        expression

Onde o arquivo expressionestá em um formato ligeiramente diferente (pense em mudar de assunto e ordem verbal em uma frase).

Portanto, seu código [x+1 for x in l if x >= 45]faz isso:

for x in l:
    if x >= 45:
        x+1

No entanto, este código [x+1 if x >= 45 else x+5 for x in l]faz isso (depois de reorganizar o expression):

for x in l:
    if x>=45: x+1
    else: x+5
arboc7
fonte
0

Não há necessidade de ternário if / then / else. Na minha opinião, sua pergunta pede esta resposta:

row = [unicode((x or '').strip()) for x in row]
mariotomo
fonte
0

Faça uma lista de itens em um iterável

Parece melhor generalizar primeiro todas as formas possíveis, em vez de dar respostas específicas a perguntas. Caso contrário, o leitor não saberá como a resposta foi determinada. Aqui estão algumas formas generalizadas que pensei antes de ficar com dor de cabeça tentando decidir se uma cláusula final poderia ser usada na última forma.

[expression1(item)                                        for item in iterable]

[expression1(item) if conditional1                        for item in iterable]

[expression1(item) if conditional1 else expression2(item) for item in iterable]

[expression1(item) if conditional1 else expression2(item) for item in iterable if conditional2]

O valor de itemnão precisa ser usado em nenhuma das cláusulas condicionais. A conditional3pode ser usado como uma opção para adicionar ou não adicionar um valor à lista de saída.

Por exemplo, para criar uma nova lista que elimine cadeias vazias ou cadeias de espaço em branco da lista original de cadeias:

newlist = [s for s in firstlist if s.strip()]
Hewey Dewey
fonte
1
O segundo erro: como Tim respondeu em seu comentário, veja também as declarações condicionais nos documentos python. O que é bastante ilegível para mim. Resumo: somente this if condition else thatou uma expressão normal é permitida. Não value = this if condition(o que pode ser alcançado com value = this if condition else None) #
Anderium 28/11/19
0

Você pode combinar lógica condicional em uma compreensão:

 ps = PorterStemmer()
 stop_words_english = stopwords.words('english')
 best = sorted(word_scores.items(), key=lambda x: x[1], reverse=True)[:10000]
 bestwords = set([w for w, s in best])


 def best_word_feats(words):
   return dict([(word, True) for word in words if word in bestwords])

 # with stemmer
 def best_word_feats_stem(words):
   return dict([(ps.stem(word), True) for word in words if word in bestwords])

 # with stemmer and not stopwords
 def best_word_feats_stem_stop(words):
   return dict([(ps.stem(word), True) for word in words if word in bestwords and word not in stop_words_english])
Max Kleiner
fonte
-2
# coding=utf-8

def my_function_get_list():
    my_list = [0, 1, 2, 3, 4, 5]

    # You may use map() to convert each item in the list to a string, 
    # and then join them to print my_list

    print("Affichage de my_list [{0}]".format(', '.join(map(str, my_list))))

    return my_list


my_result_list = [
   (
       number_in_my_list + 4,  # Condition is False : append number_in_my_list + 4 in my_result_list
       number_in_my_list * 2  # Condition is True : append number_in_my_list * 2 in my_result_list
   )

   [number_in_my_list % 2 == 0]  # [Condition] If the number in my list is even

   for number_in_my_list in my_function_get_list()  # For each number in my list
]

print("Affichage de my_result_list [{0}]".format(', '.join(map(str, my_result_list))))

(venv) $ python list_comp.py Nome
da minha lista [0, 1, 2, 3, 4, 5]
Nome da minha lista [0, 5, 4, 7, 8, 9]

Então, para você: row = [('', unicode(x.strip()))[x is not None] for x in row]

Trop Freshloïc
fonte
O que significa "Affichage de ..." ? É francês?
Peter Mortensen