2008-11-27 7 views
9

In C++ tun oft so etwas wie diese:Was ist äquivalent zu map <int, vector <int>> in Python?

typedef map<int, vector<int> > MyIndexType; 

Wo ich es dann wie folgt verwenden:

MyIndexType myIndex; 
for(... some loop ...) 
{ 
    myIndex[someId].push_back(someVal); 
} 

Wenn in der Karte gibt es keinen Eintrag den Code ein neue leere Vektor einfügen und dann anhängen.

In Python würde es so aussehen:

myIndex = {} 

for (someId,someVal) in collection: 
    try: 
     myIndex[someId].append(someVal) 
    except KeyError: 
     myIndex[someId] = [someVal] 

Der Versuch, außer ein bisschen hier hässlich. Gibt es eine Möglichkeit, dem Wörterbuch einen Objekttyp mitzuteilen, der eingefügt werden soll, wenn ein KeyError bei der Deklarationszeit des Wörterbuchs auftritt?

+0

Sie sollten in multimap <> für Ihren C++ - Code suchen. – SoapBox

+0

Eine Multimap ist hier nicht unbedingt die richtige Datenstruktur. Das Verschachteln eines Vektors in einer Karte ist in Ordnung. –

+0

Zustimmen: ein multimap würde nicht die Reihenfolge der Einfügung als Karte beibehalten > würde. – Alastair

Antwort

15

Sie verwenden möchten:

from collections import defaultdict 
myIndex = defaultdict(list) 
myIndex[someId].append(someVal) 

Standard Library defaultdict objects.

Beispiel für die Verwendung von der Python-Dokumentation:

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

So etwas wie dies vielleicht:

myIndex = {} 
for (someId,someVal) in collection: 
    myIndex.setdefault(someId, []).append(someVal) 
+0

Dies ist grundsätzlich eine bessere Art, Dinge zu tun als die Antwort von ddaa. – Jerub

+0

@Jerub: Ich stimme nicht zu. Die Verwendung eines Standarddiktes ist viel einfacher zu lesen und hat den Vorteil, dass es keine neue leere Liste erstellt und sofort zerstört, auch wenn es keinen neuen Schlüssel hinzufügt (obwohl es in der Praxis etwas langsamer für Listen ist)). – Brian

+0

Ich stimme zu.setdefault() ist der Weg zu gehen. –

0

Wie wäre das? Es ist möglicherweise nicht leistungsoptimal, aber ich denke, es ist die "einfachste Sache, die möglicherweise funktionieren könnte".

myIndex = {} 

for (someId,someVal) in collection: 
    if someId not in myIndex: 
     myIndex[someId] = [] 
    myIndex[someId].append(someVal) 
+0

Sie machen hier tatsächlich 2 Suchvorgänge. Ein mehr als nötig. –

+0

Dies wird als "look before you leap" (LBYL) bezeichnet. Mehr Python ist EAFP (google es :-)). In diesem Fall: Versuch: MyIndex [someID] .append (someVal) außer KeyError: MyIndex [someID] = [someVal] Natürlich haben wir in diesen Tagen defaultdict die :-) –

+0

noch besser ist die letzte Zeile des Beispiels sollte lesen myIndex [someId] .append (someVal) Beachten Sie das Kleinbuchstabe 'a' in 'append' –

2

nur die Antwort von Alastair abzuschließen: Es gibt auch die erhalten Äquivalent setdefault, die aufgerufen wird, erhalten (und nicht getDefault, wie man denken könnte):

myIndex = {} 
someId = None 
myList = myIndex.get(someId, []) # myList is [] now 
1

Von Python 2.5 und können Sie das Verhalten von setdefault oder defaultdict durch die Implementierung

erhalten

wie in Anmerkung 10 here.

Verwandte Themen