Python membuat kamus daftar

214

Saya ingin membuat kamus yang nilainya daftar. Sebagai contoh:

{
  1: ['1'],
  2: ['1','2'],
  3: ['2']
}

Jika aku melakukan:

d = dict()
a = ['1', '2']
for i in a:
    for j in range(int(i), int(i) + 2): 
        d[j].append(i)

Saya mendapatkan KeyError, karena d [...] bukan daftar. Dalam hal ini, saya dapat menambahkan kode berikut setelah penugasan a untuk menginisialisasi kamus.

for x in range(1, 4):
    d[x] = list()

Apakah ada cara yang lebih baik untuk melakukan ini? Katakanlah saya tidak tahu kunci yang akan saya butuhkan sampai saya berada di forloop kedua . Sebagai contoh:

class relation:
    scope_list = list()
...
d = dict()
for relation in relation_list:
    for scope_item in relation.scope_list:
        d[scope_item].append(relation)

Alternatif kemudian akan diganti

d[scope_item].append(relation)

dengan

if d.has_key(scope_item):
    d[scope_item].append(relation)
else:
    d[scope_item] = [relation,]

Apa cara terbaik untuk menangani ini? Idealnya, menambahkan akan "hanya berfungsi". Apakah ada cara untuk menyatakan bahwa saya ingin kamus daftar kosong, bahkan jika saya tidak tahu setiap kunci ketika saya pertama kali membuat daftar?

pengguna118662
sumber

Jawaban:

278

Anda dapat menggunakan defaultdict :

>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> a = ['1', '2']
>>> for i in a:
...   for j in range(int(i), int(i) + 2):
...     d[j].append(i)
...
>>> d
defaultdict(<type 'list'>, {1: ['1'], 2: ['1', '2'], 3: ['2']})
>>> d.items()
[(1, ['1']), (2, ['1', '2']), (3, ['2'])]
mechanical_meat
sumber
1
Kamus lain di bawah collectionsmodul juga bekerja dengan cara ini, misalnya collections.OrderedDict.
txsaw1
2
Oh Ini bagus. Dan Anda tidak perlu menginisialisasi ke '= []'. Barang bagus!
Wilmer E. Henao
1
NameError: name 'a' is not defined
S Andrew
51

Anda dapat membangunnya dengan pemahaman daftar seperti ini:

>>> dict((i, range(int(i), int(i) + 2)) for i in ['1', '2'])
{'1': [1, 2], '2': [2, 3]}

Dan untuk bagian kedua dari pertanyaan Anda gunakan defaultdict

>>> from collections import defaultdict
>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
        d[k].append(v)

>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
Nadia Alramli
sumber
32

Anda bisa menggunakan setdefault:

d = dict()
a = ['1', '2']
for i in a:
    for j in range(int(i), int(i) + 2): 
        d.setdefault(j, []).append(i)

print d  # prints {1: ['1'], 2: ['1', '2'], 3: ['2']}

Yang agak aneh namanya setdefault "Dapatkan nilai dengan kunci ini, atau jika kunci itu tidak ada, tambahkan nilai ini dan kemudian kembalikan."

Seperti yang orang lain tunjukkan dengan tepat, defaultdictadalah pilihan yang lebih baik dan lebih modern. setdefaultmasih berguna dalam versi Python yang lebih lama (sebelum 2.5).

RichieHindle
sumber
2
Ini berfungsi, tetapi biasanya lebih disukai menggunakan defaultdict saat tersedia.
David Z
@ David, yeah, setdefault bukan yang paling brilian dari desain, maaf - itu hampir tidak pernah menjadi pilihan terbaik. Saya pikir kita (komuter Python) menebus reputasi kolektif kita dengan collections.defaultdict, meskipun ;-).
Alex Martelli
@ DavidZ, setdefault berbeda dari defaultdict, karena lebih fleksibel: selain itu, bagaimana Anda menentukan nilai standar yang berbeda untuk kunci kamus yang berbeda?
Alex Gidan
@AlexGidan Itu benar, tetapi tidak terlalu relevan dengan pertanyaan ini.
David Z
Jawaban ini juga berguna ketika Anda membutuhkan OrderedDict dan nilai default.
nimcap
2

Pertanyaan Anda telah dijawab, tetapi IIRC Anda dapat mengganti baris seperti:

if d.has_key(scope_item):

dengan:

if scope_item in d:

Artinya, dreferensi d.keys()dalam konstruksi itu. Kadang defaultdict- kadang bukan pilihan terbaik (misalnya, jika Anda ingin mengeksekusi beberapa baris kode setelah elsedikaitkan dengan di atas if), dan saya menemukan insintaks lebih mudah dibaca.

spiffyman
sumber
2

Secara pribadi, saya hanya menggunakan JSON untuk mengubah hal menjadi string dan kembali. String saya mengerti.

import json
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
mydict = {}
hash = json.dumps(s)
mydict[hash] = "whatever"
print mydict
#{'[["yellow", 1], ["blue", 2], ["yellow", 3], ["blue", 4], ["red", 1]]': 'whatever'}
john ktejik
sumber
1

cara mudah adalah:

a = [1,2]
d = {}
for i in a:
  d[i]=[i, ]

print(d)
{'1': [1, ], '2':[2, ]}
Henning Lee
sumber