Pemahaman Kamus Python


386

Apakah mungkin untuk membuat pemahaman kamus dengan Python (untuk kunci)?

Tanpa pemahaman daftar, Anda dapat menggunakan sesuatu seperti ini:

l = []
for n in range(1, 11):
    l.append(n)

Kami dapat mempersingkat ini ke daftar pemahaman: l = [n for n in range(1, 11)].

Namun, katakan saya ingin mengatur kunci kamus ke nilai yang sama. Dapat saya lakukan:

d = {}
for n in range(1, 11):
     d[n] = True # same value for each

Saya sudah mencoba ini:

d = {}
d[i for i in range(1, 11)] = True

Namun, saya mendapatkan SyntaxErrorpada for.

Selain itu (saya tidak memerlukan bagian ini, tetapi hanya ingin tahu), dapatkah Anda mengatur kunci kamus ke sekelompok nilai yang berbeda, seperti ini:

d = {}
for n in range(1, 11):
    d[n] = n

Apakah ini mungkin dengan pemahaman kamus?

d = {}
d[i for i in range(1, 11)] = [x for x in range(1, 11)]

Ini juga menimbulkan SyntaxErrorpada for.


3
Untuk info pembaca di masa mendatang: Array NumPy memungkinkan Anda mengatur beberapa elemen menjadi satu nilai atau daftar nilai, seperti yang Anda coba lakukan. Meskipun jika Anda belum memiliki alasan untuk menggunakan NumPy, itu mungkin tidak layak hanya untuk fitur ini.
David Z

Jawaban:


520

Ada pemahaman kamus di Python 2.7+ , tetapi mereka tidak berfungsi seperti yang Anda coba. Seperti pemahaman daftar, mereka membuat kamus baru ; Anda tidak dapat menggunakannya untuk menambahkan kunci ke kamus yang ada. Selain itu, Anda harus menentukan kunci dan nilai, meskipun tentu saja Anda dapat menentukan nilai dummy jika Anda mau.

>>> d = {n: n**2 for n in range(5)}
>>> print d
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Jika Anda ingin mengatur semuanya ke True:

>>> d = {n: True for n in range(5)}
>>> print d
{0: True, 1: True, 2: True, 3: True, 4: True}

Apa yang tampaknya Anda tanyakan adalah cara untuk mengatur beberapa kunci sekaligus pada kamus yang ada. Tidak ada jalan pintas langsung untuk itu. Anda bisa mengulang seperti yang sudah Anda tunjukkan, atau Anda bisa menggunakan pemahaman kamus untuk membuat dict baru dengan nilai-nilai baru, dan kemudian lakukan oldDict.update(newDict)untuk menggabungkan nilai-nilai baru ke dalam dict lama.


15
FWIW, dict.updatejuga dapat menerima iterable dari pasangan kunci-nilai seperti dictkonstruktor
mgilson

6
Perhatikan bahwa jika Anda membuat kamus dengan semua nilai yang sama, gunakan dict.fromkeys(). Jadi untuk mengatur semua nilai True, gunakan dict.fromkeys(range(5), True). Hati-hati, nilainya tidak disalin , jadi Anda mungkin ingin menghindari ini ketika Anda memiliki nilai yang bisa diubah; itu akan dibagikan di antara semua kunci.
Martijn Pieters

2
Catatan: tombol dapat hasil dari metode juga: { n*2 : n for n in range(3) } => {0: 0, 2: 1, 4: 2}. Keduanya dapat dilakukan dalam ekspresi yang sama: { n*2 : n*3 for n in range(3) } => { 0: 0, 2: 3, 4: 6 }.
Zaaier

151

Anda dapat menggunakan dict.fromkeysmetode kelas ...

>>> dict.fromkeys(range(5), True)
{0: True, 1: True, 2: True, 3: True, 4: True}

Ini adalah cara tercepat untuk membuat kamus tempat semua kunci dipetakan dengan nilai yang sama.

Tapi jangan tidak menggunakan ini dengan benda bisa berubah :

d = dict.fromkeys(range(5), [])
# {0: [], 1: [], 2: [], 3: [], 4: []}
d[1].append(2)
# {0: [2], 1: [2], 2: [2], 3: [2], 4: [2]} !!!

Jika Anda tidak benar-benar perlu menginisialisasi semua kunci, defaultdictmungkin berguna juga:

from collections import defaultdict
d = defaultdict(True)

Untuk menjawab bagian kedua, pemahaman-dikt adalah apa yang Anda butuhkan:

{k: k for k in range(10)}

Anda mungkin tidak seharusnya melakukan ini tetapi Anda juga bisa membuat subclass dictyang berfungsi agak seperti defaultdictjika Anda menimpa __missing__:

>>> class KeyDict(dict):
...    def __missing__(self, key):
...       #self[key] = key  # Maybe add this also?
...       return key
... 
>>> d = KeyDict()
>>> d[1]
1
>>> d[2]
2
>>> d[3]
3
>>> print(d)
{}

Perhatikan bahwa dalam kasus d = defaultdict(lambda: True), lambda tidak diperlukan karena True (atau seharusnya tidak) tidak bisa berubah.
rhbvkleef

28
>>> {i:i for i in range(1, 11)}
{1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10}

22

Saya sangat suka komentar @mgilson, karena jika Anda memiliki dua iterables, satu yang sesuai dengan kunci dan yang lainnya nilainya, Anda juga dapat melakukan hal berikut.

keys = ['a', 'b', 'c']
values = [1, 2, 3]
d = dict(zip(keys, values))

memberi

d = {'a': 1, 'b': 2, 'c': 3}


4
Menggunakan Pemahaman {i:j for i in keys for j in values}
Diktik

11

Gunakan dict () pada daftar tupel, solusi ini akan memungkinkan Anda untuk memiliki nilai arbitrer di setiap daftar, asalkan mereka memiliki panjang yang sama

i_s = range(1, 11)
x_s = range(1, 11)
# x_s = range(11, 1, -1) # Also works
d = dict([(i_s[index], x_s[index], ) for index in range(len(i_s))])

12
Sebagai catatan, ini adalah hal yang sama dengand = dict(zip(i_s,x_s))
mgilson

10

Pertimbangkan contoh ini menghitung kemunculan kata-kata dalam daftar menggunakan pemahaman kamus

my_list = ['hello', 'hi', 'hello', 'today', 'morning', 'again', 'hello']
my_dict = {k:my_list.count(k) for k in my_list}
print(my_dict)

Dan hasilnya adalah

{'again': 1, 'hi': 1, 'hello': 3, 'today': 1, 'morning': 1}

Ini menarik, meskipun bukan yang paling efisien karena Anda akan menghitung kunci seperti 'halo' beberapa kali
FuriousGeorge

7

Tujuan utama dari pemahaman daftar adalah untuk membuat daftar baru berdasarkan yang lain tanpa mengubah atau menghancurkan daftar asli.

Alih-alih menulis

    l = []
    for n in range(1, 11):
        l.append(n)

atau

    l = [n for n in range(1, 11)]

Anda harus menulis saja

    l = range(1, 11)

Di dua blok kode teratas Anda membuat daftar baru, mengulanginya dan hanya mengembalikan setiap elemen. Itu hanya cara mahal untuk membuat salinan daftar.

Untuk mendapatkan kamus baru dengan semua kunci disetel ke nilai yang sama berdasarkan dikt lain, lakukan ini:

    old_dict = {'a': 1, 'c': 3, 'b': 2}
    new_dict = { key:'your value here' for key in old_dict.keys()}

Anda menerima SyntaxError karena ketika Anda menulis

    d = {}
    d[i for i in range(1, 11)] = True

Anda pada dasarnya mengatakan: "Tetapkan kunci saya 'i for i in range (1, 11)' ke True" dan "i for i in range (1, 11)" bukan kunci yang valid, itu hanya kesalahan sintaksis. Jika dikte mendukung daftar sebagai kunci, Anda akan melakukan sesuatu seperti

    d[[i for i in range(1, 11)]] = True

dan tidak

    d[i for i in range(1, 11)] = True

tetapi daftar tidak dapat di hash, jadi Anda tidak dapat menggunakannya sebagai kunci dict.


-3

Anda tidak dapat hash daftar seperti itu. coba ini sebagai gantinya, ini menggunakan tuple

d[tuple([i for i in range(1,11)])] = True
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.