0

I currently have a dictionary of tuples like this:

d = {
    0: ('f', 'farm'),
    1: ('m', 'mountain'),
    2: ('h', 'house'),
    3: ('t', 'forest'),
    4: ('d', 'desert')
}

It's been working fine until I realized that I need to be able to do a reverse lookup, so given 'f' return 0, or given 'm' return 1

I know that's possible here by creating lists of the keys and values in the dict and cross-referencing them to find the position of the key, but that seems counter productive. I was wondering if there's a different data structure that would be better suited.

All the relationships here are one-to-one. 0 will always map to f, and f will always map to 0

Grav
  • 461
  • 6
  • 18

5 Answers5

2

There are already similar questions that you could use as a starting point.

How to implement an efficient bidirectional hash table?
Reverse / invert a dictionary mapping

In your specific case, the dict in its current form may be pointless. Dicts with integer keys starting from zero are just inefficient lists, but lists already have a reverse lookup method called index.

So what you could do is:

places_order = ['f', 'm', 'h', 't', 'd']

and then use places_order.index(some_letter) to get the corresponding integer. This is an O(n) operation, so I'm assuming you don't need to perform these lookups millions of times with high performance. (Otherwise, especially if the real places_order is a long list, consider dict(zip(places_order, range(len(places_order)))).)

In addition, you could keep a map for the abbreviations of place names.

abbreviations = {
    'f': 'farm',
    'm': 'mountain',
    'h': 'house',
    't': 'forest',
    'd': 'desert'
}

It's hard to say more without knowing any specifics about what you are trying to achieve.

timgeb
  • 76,762
  • 20
  • 123
  • 145
1

A most straightforward search would be:

def search(dictionary, word):
    for key,value in dictionary.items():
        if word in value:
            return key

This could then be used as:

>>> search(d, 'h')
2
1

Not sure I fully understand the use-case, but if you are not looking for a built-in python what about pandas.Series:

import pandas as pd

d = pd.Series(['farm', 'mountain', 'house', 'forest', 'desert'],index = ['f', 'm', 'h', 't', 'd'])

so both d[0] and d['f'] will output 'farm', d.index[0] will give 'f' and d.index.get_loc('f') will give 0.

For the case of built-ins see @timgeb's answer or consider a sort of namedtuple.

LemonPy
  • 500
  • 4
  • 12
0

You can use a dict like this:

abs = {
'f': 'farm',
'm': 'mountain',
'h': 'house',
't': 'forest',
'd': 'desert'
}

when you need to reverse loop:

for i, (key, value) in enumerate(abs.items()):
    print(i, key, value)  # 0 f farm

when you want items by index:

list(abs.items())[i]  # ('f', 'farm')
Was'
  • 496
  • 4
  • 21
0

Here is another approach:

d = {
    0: ('f', 'farm'),
    1: ('m', 'mountain'),
    2: ('h', 'house'),
    3: ('t', 'forest'),
    4: ('d', 'desert')
}
for key, value in d.items():
    if 'h' in value:
        print (key)
        break
Bhagyesh Dudhediya
  • 1,800
  • 1
  • 13
  • 16