jika / ada dalam daftar pemahaman

Jawaban:

1461

Anda benar-benar dapat melakukannya. Ini hanya masalah pemesanan:

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

Secara umum,

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

Dan, untuk pemahaman daftar ifhanya dengan ketentuan,

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

Perhatikan bahwa ini sebenarnya menggunakan konstruksi bahasa yang berbeda, ekspresi kondisional , yang dengan sendirinya bukan bagian dari sintaksis pemahaman , sedangkan bagian ifsetelahnya for…inadalah bagian dari daftar pemahaman dan digunakan untuk menyaring elemen dari sumber yang dapat diubah.


Ekspresi bersyarat dapat digunakan dalam semua jenis situasi di mana Anda ingin memilih antara dua nilai ekspresi berdasarkan kondisi tertentu. Ini melakukan hal yang sama dengan operator ternary ?:yang ada dalam bahasa lain . Sebagai contoh:

value = 123
print(value, 'is', 'even' if value % 2 == 0 else 'odd')
menyodok
sumber
141
Perhatikan bahwa if / else di sini sekarang sintaks "operator ternary" dan bukan daftar sintaksis pemahaman.
Adam Vandenberg
8
Itu sebabnya saya lebih suka menempatkan operator ternary di dalam kurung, itu membuatnya lebih jelas bahwa itu hanya ekspresi normal, bukan pemahaman.
Jochen Ritzel
17
Jadi triknya adalah "Dalam kompresi daftar saya menulis jika sebelum untuk kemudian saya harus menambahkan bagian lain juga". karena jika saya l = [ 2, 3, 4, 5]kemudian [x if x % 2 == 0 for x in l]memberi saya kesalahan sementara [x if x % 2 == 0 else 200 for x in l]berfungsi. Ya saya tahu untuk memfilternya saya harus menulis [ x for x in l if x % 2 == 0]. Maaf mengganggu. Terima kasih atas jawaban anda.
Grijesh Chauhan
5
The docs python menyebutkan operator ternary . Perhatikan bahwa ini membutuhkan yang lain, atau tidak berfungsi.
naught101
4
@Drewdin Daftar pemahaman tidak mendukung pemecahan selama iterasinya. Anda harus menggunakan loop normal.
colok
44

Satu arah:

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

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

Meskipun begitu Anda memiliki:

row = map(change, row)

Atau Anda dapat menggunakan inline lambda.

Adam Vandenberg
sumber
13
Ini juga merupakan teknik yang baik (mungkin saja) untuk digunakan ketika Anda harus menangani kemungkinan pengecualian dari ifekspresi atau kode di elseblok pernyataannya. Jawaban yang diterima lebih baik untuk kasus-kasus sederhana.
martineau
37

Berikut adalah contoh ilustrasi lain:

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

Ini mengeksploitasi fakta yang if imengevaluasi Falseuntuk 0dan Trueuntuk semua nilai lain yang dihasilkan oleh fungsi range(). Oleh karena itu pemahaman daftar mengevaluasi sebagai berikut:

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

Masalah khusus telah dipecahkan dalam jawaban sebelumnya, jadi saya akan membahas gagasan umum menggunakan persyaratan dalam pemahaman daftar.

Berikut adalah contoh yang menunjukkan bagaimana kondisional dapat ditulis dalam pemahaman daftar:

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

Perhatikan bahwa dalam pemahaman daftar pertama X_non_str, urutannya adalah:

ekspresi untuk item dalam iterable jika kondisi

dan dalam pemahaman daftar terakhir X_str_changed, urutannya adalah:

ekspresi1 jika kondisi lain ekspresi2 untuk item di iterable

Saya selalu merasa sulit untuk mengingat bahwa ekspresi1 harus sebelum jika dan ekspresi2 harus setelah yang lain . Kepalaku ingin keduanya sebelum atau sesudah.

Saya kira itu dirancang seperti itu karena menyerupai bahasa normal, misalnya "Saya ingin tinggal di dalam jika hujan, kalau tidak saya ingin pergi ke luar"

Dalam bahasa Inggris biasa , dua jenis pemahaman daftar yang disebutkan di atas dapat dinyatakan sebagai:

Dengan hanya if:

extract_apple untuk apple di box_of_apples jika apple_is_ripe

dan dengan if/else

mark_apple jika apple_is_ripe lain tinggalkan_it_ tidak ditandai untuk apel di box_of_apples

Tim Skov Jacobsen
sumber
7

Solusi lain sangat bagus untuk satu if/ elsekonstruksi. Namun, pernyataan ternary dalam pemahaman daftar bisa dibilang sulit dibaca.

Menggunakan fungsi membantu keterbacaan, tetapi solusi seperti itu sulit untuk diperluas atau diadaptasi dalam alur kerja di mana pemetaan adalah input. Kamus dapat mengatasi masalah ini:

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
sumber
1

Ini berkaitan dengan bagaimana pemahaman daftar dilakukan.

Ingatlah yang berikut:

[ expression for item in list if conditional ]

Setara dengan:

for item in list:
    if conditional:
        expression

Di mana expressionada dalam format yang sedikit berbeda (berpikir beralih subjek dan urutan kata kerja dalam kalimat).

Karenanya, kode Anda [x+1 for x in l if x >= 45]melakukan ini:

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

Namun, kode ini [x+1 if x >= 45 else x+5 for x in l]melakukan ini (setelah mengatur ulang expression):

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

Tidak ada kebutuhan untuk ternary jika / lalu / selain itu. Menurut pendapat saya, pertanyaan Anda memerlukan jawaban ini:

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

Buat daftar dari item dalam iterable

Tampaknya lebih baik untuk menggeneralisasi semua formulir yang mungkin daripada memberikan jawaban spesifik untuk pertanyaan. Kalau tidak, pembaca tidak akan tahu bagaimana jawabannya ditentukan. Berikut adalah beberapa bentuk umum yang saya pikirkan sebelum saya sakit kepala mencoba untuk memutuskan apakah klausul final lain dapat digunakan dalam bentuk terakhir.

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

Nilai itemtidak perlu digunakan dalam salah satu klausa bersyarat. A conditional3dapat digunakan sebagai saklar untuk menambah atau tidak menambahkan nilai ke daftar output.

Misalnya, untuk membuat daftar baru yang menghilangkan string kosong atau string spasi putih dari daftar string asli:

newlist = [s for s in firstlist if s.strip()]
Hewey Dewey
sumber
1
Yang kedua memberikan kesalahan saat Tim menjawab dalam komentarnya, lihat juga pernyataan kondisional dalam python docs. Yang sangat tidak terbaca bagi saya. Ringkasan: hanya this if condition else thatatau ekspresi normal diizinkan. Tidak value = this if condition(yang bisa diraih dengan value = this if condition else None)
Anderium
0

Anda dapat menggabungkan logika kondisional dalam pemahaman:

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

Jadi, untuk Anda: row = [('', unicode(x.strip()))[x is not None] for x in row]

Trop Freshloïc
sumber
Apa yang dimaksud dengan "Affichage de ..." ? Apakah ini bahasa Prancis?
Peter Mortensen