Wurde bereits beantwortet, aber da mehrere Leute die Umkehrung des Wörterbuchs erwähnten, hier ist, wie man es in einer Zeile macht (unter der Annahme einer 1:1-Zuordnung) und einige verschiedene Perf-Daten:
python 2.6:
reversedict = dict([(value, key) for key, value in mydict.iteritems()])
2.7+:
reversedict = {value:key for key, value in mydict.iteritems()}
Wenn Sie glauben, dass es nicht 1:1 ist, können Sie immer noch eine vernünftige umgekehrte Zuordnung mit ein paar Zeilen erstellen:
reversedict = defaultdict(list)
[reversedict[value].append(key) for key, value in mydict.iteritems()]
Wie langsam ist das? Langsamer als eine einfache Suche, aber nicht annähernd so langsam, wie man denken würde - bei einem "einfachen" Wörterbuch mit 100000 Einträgen war eine "schnelle" Suche (d.h. die Suche nach einem Wert, der am Anfang der Schlüssel stehen sollte) etwa 10x schneller als das Umkehren des gesamten Wörterbuchs, und eine "langsame" Suche (gegen Ende) etwa 4-5x schneller. Nach höchstens 10 Suchvorgängen hat sich das System also bereits bezahlt gemacht.
die zweite Version (mit Listen pro Element) dauert etwa 2,5 Mal so lange wie die einfache Version.
largedict = dict((x,x) for x in range(100000))
# Should be slow, has to search 90000 entries before it finds it
In [26]: %timeit largedict.keys()[largedict.values().index(90000)]
100 loops, best of 3: 4.81 ms per loop
# Should be fast, has to only search 9 entries to find it.
In [27]: %timeit largedict.keys()[largedict.values().index(9)]
100 loops, best of 3: 2.94 ms per loop
# How about using iterkeys() instead of keys()?
# These are faster, because you don't have to create the entire keys array.
# You DO have to create the entire values array - more on that later.
In [31]: %timeit islice(largedict.iterkeys(), largedict.values().index(90000))
100 loops, best of 3: 3.38 ms per loop
In [32]: %timeit islice(largedict.iterkeys(), largedict.values().index(9))
1000 loops, best of 3: 1.48 ms per loop
In [24]: %timeit reversedict = dict([(value, key) for key, value in largedict.iteritems()])
10 loops, best of 3: 22.9 ms per loop
In [23]: %%timeit
....: reversedict = defaultdict(list)
....: [reversedict[value].append(key) for key, value in largedict.iteritems()]
....:
10 loops, best of 3: 53.6 ms per loop
Ich habe auch einige interessante Ergebnisse mit ifilter erzielt. Theoretisch sollte ifilter schneller sein, da wir itervalues() verwenden können und möglicherweise nicht die gesamte Werteliste erstellen bzw. durchgehen müssen. In der Praxis waren die Ergebnisse... seltsam...
In [72]: %%timeit
....: myf = ifilter(lambda x: x[1] == 90000, largedict.iteritems())
....: myf.next()[0]
....:
100 loops, best of 3: 15.1 ms per loop
In [73]: %%timeit
....: myf = ifilter(lambda x: x[1] == 9, largedict.iteritems())
....: myf.next()[0]
....:
100000 loops, best of 3: 2.36 us per loop
Bei kleinen Offsets war sie also deutlich schneller als jede frühere Version (2,36 *u*S gegenüber einem Minimum von 1,48 *m*S bei früheren Versionen). Bei großen Offsets am Ende der Liste war sie jedoch deutlich langsamer (15,1 ms gegenüber denselben 1,48 ms). Die geringen Einsparungen am unteren Ende der Liste sind die Kosten am oberen Ende nicht wert, denke ich.
0 Stimmen
Verwandt: Umkehrung / Invertierung einer Wörterbuchzuordnung
1 Stimmen
Würden Sie ein Wort anhand seiner Definition in einem Wörterbuch finden? NEIN.
0 Stimmen
Sie können eine verschlossene Tür nicht öffnen. (Es sei denn, man bricht sie auf.)