se / altro in un elenco comprensivo


Risposte:


1461

Puoi farlo totalmente. È solo un problema di ordinazione:

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

In generale,

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

E, per la comprensione dell'elenco ifsolo con condizioni,

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

Si noti che questo in realtà utilizza un costrutto di linguaggio diverso, un'espressione condizionale , che di per sé non fa parte della sintassi di comprensione , mentre il ifdopo for…inè parte delle comprensioni dell'elenco e utilizzato per filtrare elementi dalla sorgente iterabile.


Le espressioni condizionali possono essere utilizzate in tutti i tipi di situazioni in cui si desidera scegliere tra due valori di espressione in base a una condizione. Questo fa lo stesso dell'operatore ternario ?:che esiste in altre lingue . Per esempio:

value = 123
print(value, 'is', 'even' if value % 2 == 0 else 'odd')

141
Si noti che if / else qui è ora la sintassi "operatore ternario" e non la sintassi di comprensione dell'elenco.
Adam Vandenberg,

8
Ecco perché preferisco mettere l'operatore ternario tra parentesi, rende più chiaro che è solo un'espressione normale, non una comprensione.
Jochen Ritzel,

17
Quindi il trucco è "Nella compressione dell'elenco scrivo se prima per allora devo aggiungere anche un'altra parte". perché se il mio l = [ 2, 3, 4, 5]quindi [x if x % 2 == 0 for x in l]mi dà errore mentre [x if x % 2 == 0 else 200 for x in l]funziona. Sì, so che per filtrarlo dovrei scrivere [ x for x in l if x % 2 == 0]. Ci scusiamo per il disturbo. Grazie per la tua risposta.
Grijesh Chauhan,

5
I documenti di Python menzionano l'operatore ternario . Nota che richiede l'altro o non funziona.
naught101

4
La comprensione dell'elenco di @Drewdin non supporta l'interruzione durante la sua iterazione. Dovrai quindi utilizzare un ciclo normale.
colpì il

44

Senso unico:

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

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

Anche se poi hai:

row = map(change, row)

Oppure puoi usare una lambda in linea.


13
Questa è anche una buona (forse unica) tecnica da usare quando devi gestire possibili eccezioni ifdall'espressione o dal codice nel suo elseblocco di istruzioni o s. La risposta accettata è migliore per casi semplici.
martineau,

37

Ecco un altro esempio illustrativo:

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

Sfrutta il fatto che if ivaluta Falseper 0e Trueper tutti gli altri valori generati dalla funzione range(). Pertanto la comprensione dell'elenco valuta come segue:

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

37

Il problema specifico è già stato risolto nelle risposte precedenti, quindi affronterò l'idea generale di usare i condizionali nella comprensione dell'elenco.

Ecco un esempio che mostra come i condizionali possono essere scritti all'interno di una lista di comprensione:

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

Si noti che nella prima comprensione di elenco per X_non_str, l'ordine è:

espressione per l' elemento in iterabile se condizione

e nella comprensione dell'ultima lista per X_str_changed, l'ordine è:

espressione1 se condizione altro espressione2 per l' elemento in iterabile

Trovo sempre difficile ricordare che expresseion1 deve essere prima se e expression2 deve essere dopo l' altro . La mia testa vuole che sia prima o dopo.

Immagino che sia progettato in questo modo perché assomiglia al linguaggio normale, ad esempio "Voglio restare dentro se piove, altrimenti voglio andare fuori"

In parole povere i due tipi di comprensione dell'elenco sopra menzionati potrebbero essere dichiarati come:

Solo con if:

extract_apple per apple in box_of_apples se apple_is_ripe

e con if/else

mark_apple se apple_is_ripe altrimenti lascia_it_unmarked per apple in box_of_apples


7

Le altre soluzioni sono ottime per un singolo if/ elsecostrutto. Tuttavia, le dichiarazioni ternarie all'interno della comprensione dell'elenco sono probabilmente difficili da leggere.

L'uso di una funzione aiuta la leggibilità, ma tale soluzione è difficile da estendere o adattare in un flusso di lavoro in cui la mappatura è un input. Un dizionario può alleviare queste preoccupazioni:

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

1

Ha a che fare con il modo in cui viene eseguita la comprensione dell'elenco.

Tieni presente quanto segue:

[ expression for item in list if conditional ]

È equivalente a:

for item in list:
    if conditional:
        expression

Dove il expressionè in un formato leggermente diverso (pensa a cambiare l'oggetto e l'ordine dei verbi in una frase).

Pertanto, il codice [x+1 for x in l if x >= 45]fa questo:

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

Tuttavia, questo codice [x+1 if x >= 45 else x+5 for x in l]fa questo (dopo aver riorganizzato il expression):

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

0

Non c'è bisogno di ternario se / then / else. Secondo me la tua domanda richiede questa risposta:

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

0

Crea un elenco dagli elementi in un iterabile

Sembra meglio generalizzare prima tutte le forme possibili piuttosto che dare risposte specifiche alle domande. Altrimenti, il lettore non saprà come è stata determinata la risposta. Qui ci sono alcune forme generalizzate che ho pensato prima di avere un mal di testa cercando di decidere se una clausola di un altro finale potesse essere utilizzata nell'ultima 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]

Il valore del itemnon ha bisogno di essere utilizzato in una delle clausole condizionali. A conditional3può essere utilizzato come interruttore per aggiungere o non aggiungere un valore all'elenco di output.

Ad esempio, per creare un nuovo elenco che elimina stringhe vuote o stringhe di spazi bianchi dall'elenco originale di stringhe:

newlist = [s for s in firstlist if s.strip()]

1
Il secondo dà un errore quando Tim ha risposto nel suo commento, vedi anche le istruzioni condizionali nei documenti di Python. Che sono abbastanza illeggibili per me. Riepilogo: this if condition else thatè consentita solo o un'espressione normale. No value = this if condition(che può essere raggiunto con value = this if condition else None)
Anderium,

0

È possibile combinare la logica condizionale in una comprensione:

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

-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
Affichage de my_list [0, 1, 2, 3, 4, 5]
Affichage de my_result_list [0, 5, 4, 7, 8, 9]

Quindi, per te: row = [('', unicode(x.strip()))[x is not None] for x in row]


Che cosa significa "Affichage de ..." ? È francese?
Peter Mortensen,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.