Listelerin sözlüğünü oluşturan Python


214

Değerleri listeler olan bir sözlük oluşturmak istiyorum. Örneğin:

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

Eğer yaparsam:

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

Bir KeyError alıyorum, çünkü d [...] bir liste değil. Bu durumda, sözlüğü başlatmak için a'nın atanmasından sonra aşağıdaki kodu ekleyebilirim.

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

Bunu yapmanın daha iyi bir yolu var mı? İkinci fordöngüde olana kadar ihtiyacım olacak anahtarları bilmediğimi varsayalım. Örneğin:

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

Bir alternatif daha sonra

d[scope_item].append(relation)

ile

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

Bununla başa çıkmanın en iyi yolu nedir? İdeal olarak, ekleme "sadece işe yarar". Listeyi ilk oluşturduğumda her anahtarı bilmesem bile, boş listelerin sözlüğünü istediğimi ifade etmenin bir yolu var mı?

Yanıtlar:


278

Defaultdict komutunu kullanabilirsiniz :

>>> 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'])]

1
collectionsÖrneğin modül altındaki diğer sözlükler de bu şekilde çalışır collections.OrderedDict.
txsaw1

2
Ah. Bu harika. Ve '= []' olarak başlatmanız gerekmez. İyi şeyler!
Wilmer E. Henao

1
NameError: name 'a' is not defined
S Andrew

51

Liste kavrayışı ile şöyle oluşturabilirsiniz:

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

Ve sorunuzun ikinci kısmı için defaultdict kullanın

>>> 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])]

32

Şunları kullanabilirsiniz 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']}

Oldukça garip bir şekilde adlandırılan setdefaultişlev "Değeri bu anahtarla al veya bu anahtar orada değilse bu değeri ekleyin ve sonra döndürün."

Diğerlerinin haklı olarak işaret ettiği gibi, defaultdictdaha iyi ve daha modern bir seçimdir. setdefaultPython'un eski sürümlerinde hala yararlıdır (2.5'ten önce).


2
Bu işe yarar, ancak kullanılabilir olduğunda defaultdict kullanmak genellikle tercih edilir.
David Z

@David, evet, setdefault en parlak tasarım değildi, üzgünüm - neredeyse en iyi seçim değil. Bence (Python komisyoncuları) collections.defaultdict ile ortak itibarımızı kullandı ;-).
Alex Martelli

@DavidZ, setdefault, daha esnek olduğu için defaultdict'ten farklıdır: Aksi takdirde, farklı sözlük anahtarları için farklı varsayılan değerleri nasıl belirtirsiniz?
Alex Gidan

@AlexGidan Bu doğru, ancak bu soru ile özellikle ilgili değil.
David Z

Bu yanıt ayrıca bir OrderedDict ve varsayılan değere ihtiyacınız olduğunda da kullanışlıdır.
nimcap

2

Sorunuz zaten cevaplandı, ancak IIRC gibi satırları değiştirebilirsiniz:

if d.has_key(scope_item):

ile:

if scope_item in d:

Yani, o yapıdaki dreferanslar d.keys(). Bazen defaultdicten iyi seçenek değildir (örneğin, elseyukarıdakilerle ilişkilendirildikten sonra birden fazla kod satırı yürütmek istiyorsanız if) ve insözdiziminin okunmasını daha kolay buluyorum .


2

Şahsen ben sadece şeyleri dizelere ve geriye dönüştürmek için JSON kullanıyorum. Anlıyorum.

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'}

1

kolay yolu:

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

print(d)
{'1': [1, ], '2':[2, ]}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.