You hit the nail on the head that inverting dictionaries has a big problem with collisions, as values become keys. One solution to this is to use a MultiDict, a la boltons' OrderedMultiDict: https://boltons.readthedocs.org/en/latest/dictutils.html#boltons.dictutils.OrderedMultiDict.inverted

But yes, I use inversions all the time, and would love to see a MultiDict in the collections module to support that use case.

Mahmoud
https://github.com/mahmoud
http://sedimental.org

On Thu, Feb 11, 2016 at 6:14 PM, João Bernardo wrote:
Many times I have the need for a dictionary and its inverse form (keys and values swapped). For static dictionaries, it is easy, but sometimes I wish there were a class to hold and update both dictionaries at the same time. Also it will avoid creating 2 variables.

Sample:

# Current code
d = {'foo': 10, 'bar': 12, 'baz': 17}
d_inv = {v: k for k, v in d.items()}

# My proposal
d = InverseDict({'foo': 10, 'bar': 12, 'baz': 17})

d['foo'] == 10
d.inv[10] == 'foo'

This class could exist in the collections module.
The way the inverse dictionary is accessed could be different (another attribute name or another form):

d.I[10]       # Like numpy's matrix.T for transpose
d.inverse[10] # More verbose

d[10:1]       # d[10:0] and d[10] would mean the direct dict
# while d[10:1] the inverse one.
# This would limit the usage to get/set/del only...

(-d)[10]      # negative symbol but it would require parenthesis.
# (~d)[10] should be more correct because of
# the operator's name

The inverse version of the dict may or may not allow repeated items (overwrite vs error). The important part would be to remove keys from the inverse dict when the value is changed in the direct one:

d['foo'] = 1
d.inv[1] == 'foo'
d.inv[10] -> will raise KeyError instead of returning 'foo'

Regards,
João Bernardo

_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/