Python erstellt ein Listenwörterbuch

214

Ich möchte ein Wörterbuch erstellen, dessen Werte Listen sind. Beispielsweise:

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

Wenn ich mache:

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

Ich bekomme einen KeyError, weil d [...] keine Liste ist. In diesem Fall kann ich nach der Zuweisung von a den folgenden Code hinzufügen, um das Wörterbuch zu initialisieren.

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

Gibt es einen besseren Weg, dies zu tun? Nehmen wir an, ich kenne die Schlüssel nicht, die ich benötigen werde, bis ich in der zweiten forSchleife bin . Beispielsweise:

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

Eine Alternative wäre dann das Ersetzen

d[scope_item].append(relation)

mit

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

Was ist der beste Weg, um damit umzugehen? Im Idealfall würde das Anhängen "einfach funktionieren". Gibt es eine Möglichkeit auszudrücken, dass ich ein Wörterbuch mit leeren Listen möchte, auch wenn ich nicht jeden Schlüssel kenne, wenn ich die Liste zum ersten Mal erstelle?

user118662
quelle

Antworten:

278

Sie können defaultdict verwenden :

>>> 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'])]
mechanisches Fleisch
quelle
1
So collectionsfunktionieren beispielsweise auch andere Wörterbücher unter dem Modul collections.OrderedDict.
txsaw1
2
Oh. Das ist toll. Und Sie müssen nicht mit '= []' initialisieren. Gutes Zeug!
Wilmer E. Henao
1
NameError: name 'a' is not defined
S Andrew
51

Sie können es mit Listenverständnis wie folgt erstellen:

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

Und für den zweiten Teil Ihrer Frage verwenden Sie 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
quelle
32

Sie können verwenden 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']}

Die ziemlich seltsam benannte setdefaultFunktion sagt: "Holen Sie sich den Wert mit diesem Schlüssel, oder wenn dieser Schlüssel nicht vorhanden ist, fügen Sie diesen Wert hinzu und geben Sie ihn dann zurück."

Wie andere zu Recht betont haben, defaultdictist dies eine bessere und modernere Wahl. setdefaultist in älteren Versionen von Python (vor 2.5) immer noch nützlich.

RichieHindle
quelle
2
Dies funktioniert, aber es wird normalerweise bevorzugt, defaultdict zu verwenden, wenn es verfügbar ist.
David Z
@ David, ja, Setdefault war nicht das brillanteste Stück Design, sorry - es ist kaum die beste Wahl. Ich denke jedoch, dass wir (die Python-Committer) unseren kollektiven Ruf mit collection.defaultdict wieder gut gemacht haben ;-).
Alex Martelli
@DavidZ, setdefault unterscheidet sich von defaultdict, da es flexibler ist: andernfalls, wie geben Sie unterschiedliche Standardwerte für unterschiedliche Wörterbuchschlüssel an?
Alex Gidan
@AlexGidan Das stimmt, ist aber für diese Frage nicht besonders relevant.
David Z
Diese Antwort ist auch nützlich, wenn Sie ein OrderedDict und einen Standardwert benötigen.
Nimcap
2

Ihre Frage wurde bereits beantwortet, aber IIRC können Sie Zeilen ersetzen wie:

if d.has_key(scope_item):

mit:

if scope_item in d:

Das heißt, dReferenzen d.keys()in dieser Konstruktion. Manchmal defaultdictist dies nicht die beste Option (zum Beispiel, wenn Sie mehrere Codezeilen nach elseden oben genannten ausführen möchten if), und ich finde die inSyntax leichter zu lesen.

Spiffyman
quelle
2

Persönlich verwende ich JSON nur, um Dinge in Strings und zurück zu konvertieren. Saiten verstehe ich.

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
quelle
1

einfacher Weg ist:

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

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