Bagaimana saya bisa menggunakan if / else dalam pemahaman kamus?

138

Apakah ada cara di Python 2.7+ untuk membuat sesuatu seperti berikut ini?

{ something_if_true if condition else something_if_false for key, value in dict_.items() }

Saya tahu Anda bisa membuat apa saja hanya dengan 'jika':

{ something_if_true for key, value in dict_.items() if condition}
diegueus9
sumber
4
seperti yang diceritakan oleh @Marcin, a dictterbuat dari key:valueelemen, Anda tidak membangun di dictsini tetapi a set(lihat himpunan literal ).
mdeous

Jawaban:

247

Anda sudah mendapatkannya: A if test else B adalah ekspresi Python yang valid. Satu-satunya masalah dengan pemahaman dict Anda seperti yang ditunjukkan adalah bahwa tempat untuk ekspresi dalam pemahaman dict harus memiliki dua ekspresi, dipisahkan oleh titik dua:

{ (some_key if condition else default_key):(something_if_true if condition
          else something_if_false) for key, value in dict_.items() }

ifKlausa terakhir bertindak sebagai filter, yang berbeda dari memiliki ekspresi kondisional.

Marcin
sumber
28
Layak disebutkan bahwa Anda tidak perlu memiliki kondisi if-else untuk kunci dan nilainya. Misalnya {(a if condition else b): value for key, value in dict.items()}akan bekerja.
Jeremy Weirich
5
@JeremyWeirich Anda tidak perlu memiliki if-else untuk salah satu dari mereka jika Anda tidak mau.
Marcin
@ Marsin Apakah mungkin bagi saya untuk menggunakan hanya "jika" untuk bagian kunci dan menggunakan "jika" dan "lain" untuk bagian nilai?
nithin11
14

Jawaban @ Marcin mencakup semuanya, tetapi kalau-kalau seseorang ingin melihat contoh aktual, saya tambahkan dua di bawah ini:

Katakanlah Anda memiliki kamus set berikut

d = {'key1': {'a', 'b', 'c'}, 'key2': {'foo', 'bar'}, 'key3': {'so', 'sad'}}

dan Anda ingin membuat kamus baru yang kuncinya menunjukkan apakah string 'a'tersebut terkandung dalam nilai atau tidak, Anda dapat menggunakan

dout = {"a_in_values_of_{}".format(k) if 'a' in v else "a_not_in_values_of_{}".format(k): v for k, v in d.items()}

yang menghasilkan

{'a_in_values_of_key1': {'a', 'b', 'c'},
 'a_not_in_values_of_key2': {'bar', 'foo'},
 'a_not_in_values_of_key3': {'sad', 'so'}}

Sekarang anggaplah Anda memiliki dua kamus seperti ini

d1 = {'bad_key1': {'a', 'b', 'c'}, 'bad_key2': {'foo', 'bar'}, 'bad_key3': {'so', 'sad'}}
d2 = {'good_key1': {'foo', 'bar', 'xyz'}, 'good_key2': {'a', 'b', 'c'}}

dan Anda ingin mengganti kunci d1dengan kunci d2jika ada nilai masing-masing identik, Anda bisa melakukannya

# here we assume that the values in d2 are unique
# Python 2
dout2 = {d2.keys()[d2.values().index(v1)] if v1 in d2.values() else k1: v1 for k1, v1 in d1.items()}

# Python 3
dout2 = {list(d2.keys())[list(d2.values()).index(v1)] if v1 in d2.values() else k1: v1 for k1, v1 in d1.items()}

pemberian yang mana

{'bad_key2': {'bar', 'foo'},
 'bad_key3': {'sad', 'so'},
 'good_key2': {'a', 'b', 'c'}}
Cleb
sumber
untuk contoh kedua Anda menggunakan d1, d2saya mendapatkanAttributeError: 'dict_values' object has no attribute 'index'
alancalvitti
@alancalvitti: terima kasih telah menunjukkan ini! Solusinya adalah untuk Python 2 dan tidak bekerja untuk Python 3; Saya menambahkan solusi Python 3 juga.
Cleb
3

Jika Anda memiliki kondisi yang berbeda untuk mengevaluasi kunci dan nilai, jawaban @ Marcin adalah cara yang harus dilakukan.

Jika Anda memiliki kondisi yang sama untuk kunci dan nilai, Anda lebih baik dengan membangun (kunci, nilai) -tupel dalam ekspresi generator yang memasukkan dict():

dict((modify_k(k), modify_v(v)) if condition else (k, v) for k, v in dct.items())

Lebih mudah dibaca dan kondisinya hanya dievaluasi sekali per kunci, nilainya.

Contoh dengan meminjam set kamus @ Cleb:

d = {'key1': {'a', 'b', 'c'}, 'key2': {'foo', 'bar'}, 'key3': {'so', 'sad'}}

Asumsikan Anda ingin sufiks hanya keysdengan adi dalamnya valuedan Anda ingin valuediganti dengan panjang set dalam kasus seperti itu. Jika tidak, pasangan nilai kunci harus tetap tidak berubah.

dict((f"{k}_a", len(v)) if "a" in v else (k, v) for k, v in d.items())
# {'key1_a': 3, 'key2': {'bar', 'foo'}, 'key3': {'sad', 'so'}}
Darkonaut
sumber
0

Contoh lain dalam menggunakan if / else dalam pemahaman kamus

Saya bekerja pada aplikasi desktop entri data untuk pekerjaan kantor saya sendiri, dan itu umum untuk aplikasi entri data seperti itu untuk mendapatkan semua entri dari widget input dan membuangnya ke kamus untuk diproses lebih lanjut seperti validasi, atau mengedit yang harus kita kembalikan data yang dipilih dari file kembali ke widget entri, dll.

Babak pertama menggunakan coding tradisional (8 baris):

entries = {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}

a_dic, b_dic = {}, {}

for field, value in entries.items():
    if field == 'ther':
        for k,v in value.items():
            b_dic[k] = v
        a_dic[field] = b_dic
    else:
        a_dic[field] = value
    
print(a_dic)
 {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}”

Babak kedua saya mencoba menggunakan pemahaman kamus tetapi loop masih ada (6 baris):

entries = {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}

for field, value in entries.items():
    if field == 'ther':
        b_dic = {k:v for k,v in value.items()}
        a_dic[field] = b_dic
    else:
        a_dic[field] = value
    
print(a_dic)
 {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}”

Akhirnya, dengan pernyataan pemahaman kamus satu baris (1 baris):

entries = {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}

a_dic = {field:{k:v for k,v in value.items()} if field == 'ther' 
        else value for field, value in entries.items()}
    
print(a_dic)
 {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}”

Saya menggunakan python 3.8.3

KokoEfraim
sumber