Python dict cara membuat kunci atau menambahkan elemen ke kunci?

161

Saya punya kamus kosong. Nama: dict_x Memiliki kunci yang nilainya daftar.

Dari iterasi yang terpisah, saya mendapatkan kunci (ex:) key_123, dan item (tuple) untuk ditempatkan dalam daftar dict_xnilai key_123.

Jika kunci ini sudah ada, saya ingin menambahkan item ini. Jika kunci ini tidak ada, saya ingin membuatnya dengan daftar kosong dan kemudian menambahkannya atau hanya membuatnya dengan tuple di dalamnya.

Di masa depan ketika lagi kunci ini muncul, karena ada, saya ingin nilai ditambahkan lagi.

Kode saya terdiri dari ini:

Dapatkan kunci dan nilai.

Lihat apakah kunci NOT ada di dict_x.

dan jika tidak membuatnya: dict_x[key] == []

Setelah itu: dict_x[key].append(value)

Apakah ini cara untuk melakukannya? Haruskah saya mencoba menggunakan try/exceptblok?

Phil
sumber

Jawaban:

254

Gunakan dict.setdefault():

dic.setdefault(key,[]).append(value)

bantuan (dict.setdefault) :

    setdefault(...)
        D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D
Ashwini Chaudhary
sumber
4
Saya biasa melakukan ini dict_x[key] = [some_value] if not dict_x.has_key(key) else dict_x[key] + [some_value]tetapi jawaban ini menyarankan cara yang jauh lebih baik. Bahkan itu didapat set()sebagai argumen dan memungkinkan Anda untuk menggunakan add()metode ...
fatih_dur
66

Berikut adalah berbagai cara untuk melakukan ini sehingga Anda dapat membandingkan tampilannya dan memilih apa yang Anda suka. Saya telah memesannya dengan cara yang saya pikir paling "pythonic" , dan berkomentar pro dan kontra yang mungkin tidak jelas pada pandangan pertama:

Menggunakan collections.defaultdict:

import collections
dict_x = collections.defaultdict(list)

...

dict_x[key].append(value)

Pro: Mungkin kinerja terbaik. Cons: Tidak tersedia dalam Python 2.4.x.

Menggunakan dict().setdefault():

dict_x = {}

...

dict_x.setdefault(key, []).append(value)

Cons: Penciptaan yang tidak efisien list()s.

Menggunakan try ... except:

dict_x = {}

...

try:
    values = dict_x[key]
except KeyError:
    values = dict_x[key] = []
values.append(value)

Atau:

try:
    dict_x[key].append(value)
except KeyError:
    dict_x[key] = [value]
antak
sumber
Halo, mengapa menurut Anda .setdefault membuat kamus yang tidak perlu?
Phil
2
Saya tidak berpikir .setdefault()membuat kamus yang tidak perlu. Saya pikir saya membuat yang tidak perlu list(yaitu []) dalam argumen kedua .setdefault()yang tidak pernah digunakan jika keysudah ada. Saya bisa menggunakan dict.setdefault()(untuk kepentingan hashing kunci yang efisien), dan menggunakan variabel untuk menggunakan kembali yang tidak digunakan listtetapi itu menambahkan beberapa baris kode lagi.
antak
1
IIRC, dalam Python daftar kosong dalam kesetaraan dianggap konstan pada level bytecode, tetapi ini membutuhkan konfirmasi oleh seorang bytecode guru (atau hanya menggunakan modul disas).
Gaborous
Menggunakan .setdefaultmenciptakan biasa di dictmana absen kunci pencarian akan menghasilkan beberapa KeyErrorsaat collections.defaultdict(list)menciptakan menciptakan di dictmana absen kunci pencarian akan memasukkan kosong list- saya pikir Anda harus memilih berdasarkan perilaku yang Anda inginkan
Chris_Rands
Saya mencoba sesuatu yang mirip dengan collections.defaultdict dalam kode saya sendiri dan itu memiliki efek samping yang tidak terduga. Misalnya perhatikan pertukaran IDLE berikut: >>> list_dict = defaultdict (daftar) >>> len (list_dict) 0 >>> len (list_dict [0]) 0 >>> len (list_dict) 1 Tampaknya ketika Python memanggil nilai default itu menambahkan kunci ke kamus tanpa Anda secara aktif mengaturnya, yang akan membuat banyak daftar kosong jika default banyak digunakan. Saya akan menjalankan fungsi wrapper saya sendiri untuk kamus, tidak efisien tapi mudah-mudahan lebih dapat diprediksi.
RDBury
26

Anda dapat menggunakan defaultdict untuk ini.

from collections import defaultdict
d = defaultdict(list)
d['key'].append('mykey')

Ini sedikit lebih efisien daripada setdefaultkarena Anda tidak membuat daftar baru yang akhirnya tidak Anda gunakan. Setiap panggilan ke setdefaultakan membuat daftar baru, bahkan jika item sudah ada di kamus.

Nathan Villaescusa
sumber
14

Anda dapat menggunakan defaultdict di collections.

Contoh dari doc:

s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
d = defaultdict(list)
for k, v in s:
    d[k].append(v)
iMom0
sumber
0
dictionary['key'] = dictionary.get('key', []) + list_to_append
Tomas Silva Ebensperger
sumber
1
Anda harus menjelaskan keuntungan (sangat kecil) yang ada di hadapan pengecualian tertentu; hanya sebagai kode, tidak jelas mengapa jawaban tambahan diperlukan.
Davis Herring
Hai, hanya alternatif tanpa impor tambahan. Ini jelas dapat dilakukan dengan pernyataan if. Saya hanya menyarankan alternatif menggunakan kekuatan .get () daripada menggunakan dict [].
Tomas Silva Ebensperger
Dua jawaban teratas menyebutkan dua cara berbeda tanpa impor (walaupun tidak dict.get).
Davis Herring