2010-02-18 9 views
13

Chciałbym móc stworzyć słownik Pythona z ciągami jako kluczami i zestawami ciągów znaków jako wartościami. Np .: { "crackers" : ["crunchy", "salty"] } To musi być zestaw, a nie lista.Słownik w języku Python, który mapuje ciągi znaków do zestawu ciągów znaków?

Jednak kiedy próbuję następujący:

word_dict = dict() 
    word_dict["foo"] = set() 
    word_dict["foo"] = word_dict["foo"].add("baz")          
    word_dict["foo"] = word_dict["foo"].add("bang") 

uzyskać:

Traceback (most recent call last): 
    File "process_input.py", line 56, in <module> 
    test() 
    File "process_input.py", line 51, in test 
    word_dict["foo"] = word_dict["foo"].add("bang") 
AttributeError: 'NoneType' object has no attribute 'add' 

Gdybym to zrobić:

word_dict = dict() 
    myset = set() 
    myset.add("bar") 
    word_dict["foo"] = myset 
    myset.add("bang") 
    word_dict["foo"] = myset 

    for key, value in word_dict:              
     print key,                 
     print value 

uzyskać:

Traceback (most recent call last): 
    File "process_input.py", line 61, in <module> 
    test() 
    File "process_input.py", line 58, in test 
    for key, value in word_dict: 
ValueError: too many values to unpack 

Jakieś wskazówki, jak zmusić Pythona do robienia tego, co chciałbym? Jestem pośrednią użytkownika Pythona (lub tak myślałem, aż wpadłem na ten problem.)

Odpowiedz

27

set.add() nie zwraca nowy set, to modyfikuje set nazywany jest dalej. Używaj go w ten sposób:

word_dict = dict() 
word_dict["foo"] = set() 
word_dict["foo"].add("baz")          
word_dict["foo"].add("bang") 

Ponadto, jeśli używasz for pętli iteracyjne nad dict, jesteś iteracji kluczy:

for key in word_dict: 
    print key, word_dict[key] 

Ewentualnie można iteracyjne nad word_dict.items() lub word_dict.iteritems():

for key, value in word_dict.items(): 
    print key, value 
+0

Dziękuję. Oczywiście, duh. –

23
from collections import defaultdict 

word_dict = defaultdict(set) 
word_dict['banana'].add('yellow') 
word_dict['banana'].add('brown') 
word_dict['apple'].add('red') 
word_dict['apple'].add('green') 
for key,values in word_dict.iteritems(): 
    print "%s: %s" % (key, values) 
+0

+1 nie bezpośrednio odpowiedzieć na pytanie, ale z pewnością może uczynić życie PO za łatwiejsze tutaj . –

+0

Nice! To świetny pomysł. –

+0

+1 nie wiedziałem, że .. Miałem ten sam problem co OP i jest to bardzo miłe i IMO bardziej czytelne niż zaakceptowana odpowiedź. – DrColossos

1

Spróbuj:

word_dict = dict() 
myset = set() 
myset.add("bar") 
word_dict["foo"] = myset 
myset.add("bang") 
word_dict["foo"] = myset 

for key in word_dict:              
    print key, word_dict[key] 

Wygląda na to, że iterator ze standardowym słownikiem zwraca tylko key, ale nie jest krotką.

Dowód:

>>> d = { 'test': 1 } 
>>> for k, v in d: print k, v 
... 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: too many values to unpack 
>>> for k in d: print d[k] 
... 
1 
+0

Alternatywnie, 'dla klucza, wartość w word_dict.iteritems():' jest nieco dłuższa, ale ładniejsza w dostępie do 'key' i' value' IMHO. –

6

Kiedy mówisz word_dict["foo"].add("baz"), dodajesz 'baz' do zestawu word_dict [ "foo"].

Funkcja zwraca None - aktualizacja zestawu jest efektem ubocznym. Więc

word_dict["foo"] = word_dict["foo"].add("baz") 

ostatecznie ustala word_dict["foo"] do None.

Po prostu word_dict["foo"].add("baz") byłby poprawny.

W drugim scenariuszu, kiedy mówisz

for key, value in word_dict:              

napotkasz błąd, ponieważ poprawna składnia jest

for key in word_dict: 

do pętli na zaledwie kluczami w word_dict.W tej sytuacji użytkownik zamiast tego chce zamiast tego użyć stuprocentowej wartości.

1

Problem jest taki:

word_dict["foo"] = word_dict["foo"].add("baz") 

Po wywołaniu word_dict["foo"].add("baz"), jesteś mutacji zestaw, który word_dict["foo"] odnosi się do, i że operacja zwraca None. Czytając to zdanie od prawej do lewej, dodajesz "baz" do zestawu, o którym mowa, przez word_dict["foo"], a następnie ustawiając wynik tej operacji (czyli None) na word_dict["foo"].

Aby to działało zgodnie z oczekiwaniami, wystarczy usunąć word_dict["foo"] = ze swojego wyciągu.

Słowniki iteracyjne na swoich kluczy domyślnie stąd ValueError spróbować to:

for key, value in word_dict: 

Co tu się dzieje jest to, że powtarzanie word_dict wraca tylko klucz (powiedzmy, „foo”), którego” następnie próbuje rozpakować do zmiennych key & value. Rozpakowanie "foo" daje "f", "o", & "o", która jest jedną wartością za dużą, aby zmieścić się w dwóch zmiennych, a tym samym w twoim ValueError.

Jak inni stwierdzili, co chcesz, jest iteracyjne na par klucz-wartość słownika, na przykład tak:

for key, value in word_dict.iteritems(): 
Powiązane problemy