How do I make a dictionary with multiple keys to one value?

I have a question about a dictionary I want to make. My goal is to have multiple keys to a single value, like below:

dictionary = {('a', 'b'): 1, ('c', 'd'): 2}
assert dictionary['a'] == 1
assert dictionary['b'] == 1

Any ideas?


Solution 1:

I guess you mean this:

class Value:
    def __init__(self, v=None):
        self.v = v

v1 = Value(1)
v2 = Value(2)

d = {'a': v1, 'b': v1, 'c': v2, 'd': v2}
d['a'].v += 1

d['b'].v == 2 # True
  • Python's strings and numbers are immutable objects,
  • So, if you want d['a'] and d['b'] to point to the same value that "updates" as it changes, make the value refer to a mutable object (user-defined class like above, or a dict, list, set).
  • Then, when you modify the object at d['a'], d['b'] changes at same time because they both point to same object.

Solution 2:

If you're going to be adding to this dictionary frequently you'd want to take a class based approach, something similar to @Latty's answer in this SO question 2d-dictionary-with-many-keys-that-will-return-the-same-value.

However, if you have a static dictionary, and you need only access values by multiple keys then you could just go the very simple route of using two dictionaries. One to store the alias key association and one to store your actual data:

alias = {
    'a': 'id1',
    'b': 'id1',
    'c': 'id2',
    'd': 'id2'
}

dictionary = {
    'id1': 1,
    'id2': 2
}

dictionary[alias['a']]

If you need to add to the dictionary you could write a function like this for using both dictionaries:

def add(key, id, value=None)
    if id in dictionary:
        if key in alias:
            # Do nothing
            pass
        else:
            alias[key] = id
    else:
        dictionary[id] = value
        alias[key] = id

add('e', 'id2')
add('f', 'id3', 3)

While this works, I think ultimately if you want to do something like this writing your own data structure is probably the way to go, though it could use a similar structure.

Solution 3:

Your example creates multiple key: value pairs if using fromkeys. If you don't want this, you can use one key and create an alias for the key. For example if you are using a register map, your key can be the register address and the alias can be register name. That way you can perform read/write operations on the correct register.

>>> mydict = {}
>>> mydict[(1,2)] = [30, 20]
>>> alias1 = (1,2)
>>> print mydict[alias1]
[30, 20]
>>> mydict[(1,3)] = [30, 30]
>>> print mydict
{(1, 2): [30, 20], (1, 3): [30, 30]}
>>> alias1 in mydict
True