2

dictionary is usually good for find value by key,but find key by value is pretty slow

for k,v in dictionary.items():
    if v = myValue:
        return k

is there already a data structure that make both key->value and ke

Max
  • 7,957
  • 10
  • 33
  • 39
  • 2
    I'm against this being a duplicate of [Two way/reverse map](http://stackoverflow.com/questions/1456373/two-way-reverse-map) - that is a special case where keys and values never are the same, at least from its accepted answer. In the general case, this question's [accepted answer](http://stackoverflow.com/a/12527752/321973) is much better – Tobias Kienzler May 28 '13 at 13:44
  • This question is more a duplicate of [Efficient bidirectional hash table in Python?](http://stackoverflow.com/questions/3318625/efficient-bidirectional-hash-table-in-python) than the other one due to the latter's restrictions – Tobias Kienzler May 29 '13 at 06:59
  • meta.SO discussion: [How to correctly treat fupes (=fake dupes)?](http://meta.stackexchange.com/q/182141/146482) – Tobias Kienzler May 29 '13 at 09:28

3 Answers3

8

You could try bidict:

>>> husbands2wives = bidict({'john': 'jackie'})
>>> husbands2wives['john'] # the forward mapping is just like with dict
'jackie'
>>> husbands2wives[:'jackie'] # use slice for the inverse mapping
'john'
  • Do you know if this is faster than just using an inverted dict (as Martjin suggests), or does it just sugar for the same? – Andy Hayden Sep 21 '12 at 09:39
  • @hayden: bidict stores the forward and inverted dicts and provides syntactic sugar, so speedwise it's the same provided you created your inverted dict once. – Martijn Pieters Sep 21 '12 at 09:57
  • @MartijnPieters That's not entirely correct, as discussed [here](http://stackoverflow.com/questions/16793526/is-there-a-better-way-to-store-a-twoway-dictionary-than-storing-its-inverse-sepa?lq=1#comment24202891_16793526) the [source code](https://bitbucket.org/jab/bidict/src/8a2eb8d16607395954175c389ed4c7b1721c074e/bidict.py?at=default#cl-437) contains some checks that make bidict slightly slower than two pure dicts. Though for pure read access, `husbands2wives._fwd['john']` and `husband2swives._bwd['jackie']` would provide the same speed – Tobias Kienzler May 29 '13 at 14:28
  • @TobiasKienzler: Unless you are running this in a 150000 item loop, the difference is going to be minimal. :-) – Martijn Pieters May 29 '13 at 14:32
  • @MartijnPieters I perfectly agree, and read-/maintainability is more import than those few milliseconds. It's just something to keep in mind _if_ speed is crucial; and in that case explicitly using an inverse dictionary would probably be better. But in 99.9% of cases I'd say bidict is the best way – Tobias Kienzler May 31 '13 at 06:49
  • The sugar `[:val]` and `~dict` are not available anymore. Instead, go with `bidict.inv[val]` and `bidict.inv` – lifebalance Jan 03 '20 at 20:39
5

Just create an inverted mapping:

from collections import defaultdict
inverted = defaultdict(list)
for k, v in dictionary.iteritems():
    inverted[v].append(k)

Note that the above code handles duplicate values; inverted[v] returns a list of keys that hold that value.

If your values are also unique, a simple dict can be used instead of defaultdict:

inverted = { v: k for k, v in dictionary.iteritems() }

or, in python 3, where items() is a dictionary view:

inverted = { v: k for k, v in dictionary.items() }
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
0

Python 3:

revdict = {v:k for k,v in dictionary.items()}

(Python 2 use .iteritems() instead)

nneonneo
  • 171,345
  • 36
  • 312
  • 383