0

This might be a silly question, but for some reason the solution escapes me at the moment.

I would like to have fast and efficient access to data that is in a list format. So for example a list of questions:

q = {}
q[1] = "my first string"
q[2] = "my second string"
q[3] = "my third string"

I can easily find what question 2's string is by doing q[2]. But I would also like to retrieve the question number by indexing q with the string:

q["my second string"] -> gives 2 as answer

I would like to do this without iterating over the keys (defeats the purpose of a dictionary) and like to avoid defining a second dictionary using the string as the key to avoid wasted memory. Is this possible?

Ultimately the reason for this is I would like to access say q[2] or q["my second string"] and get the data associated with question 2, whether using the number or the string as a key to that data. Is this possible without having to iterating over all the keys while avoiding data duplication?

stewart99
  • 14,024
  • 7
  • 27
  • 42
  • dicts arn't bidirectional, so you either need a second dict or iterate. there's not other way. – mata Jun 28 '12 at 07:23
  • possible duplicate of [Efficient bidirectional hash table in Python?](http://stackoverflow.com/questions/3318625/efficient-bidirectional-hash-table-in-python) – ecatmur Jun 28 '12 at 07:37

4 Answers4

2

There's no problem having a mixture of int and str as keys

>>> q = {}
>>> q[1] = "my first string"
>>> q[2] = "my second string"
>>> q[3] = "my third string"
>>> q.update({v:k for k,v in q.items()})
>>> q["my second string"]
2
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
1

You can use an OrderedDict, but for one of the directions it's not going to be as efficient as a normal dictionary lookup.

from collections import OrderedDict
q = OrderedDict()
q["my first string"] = 1
q["my second string"] = 2
q["my third string"] = 3
# Now you have normal key lookups on your string as a normal dict, and to get the order
q.values()[1]  # To get the second value out
# To get the key, value pair of the second entry
q.items()[1]
# Would return `('my second string', 2)`
Christian Witts
  • 11,375
  • 1
  • 33
  • 46
0

This was asked at Efficient bidirectional hash table in Python?

The answer remains the same - use bidict from http://pypi.python.org/pypi/bidict

Community
  • 1
  • 1
ecatmur
  • 152,476
  • 27
  • 293
  • 366
0
class MyDict(dict):
    def __init__(self, **kwargs):
        super(MyDict, self).__init__(**kwargs)
        for k, v in kwargs.iteritems():
            self[v] = k
    def __setitem__(self, key, val):
        super(MyDict, self).__setitem__(key, val)
        super(MyDict, self).__setitem__(val, key)

d = MyDict(a=1, b=2)
print d[1] # "a"
print d[2] # "b"
d['c'] = 3
print d[3] # "c"