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?

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

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]

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.


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)

0
dictionary['key'] = dictionary.get('key', []) + list_to_append

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.