问题
This is really a variation on this question, but not a duplicate:
Python reverse / invert a mapping
Given a dictionary like so:
mydict= { 'a': ['b', 'c'], 'd': ['e', 'f'] }
How can one invert this dict to get:
inv_mydict = { 'b':'a', 'c':'a', 'e':'d', 'f':'d' }
Note that values span uniquely under each key.
Note: I previously had syntax map = ...
and dict = ...
Reminder not to use map
and dict
as they are built-in functions, see excellent comments and answers below :)
回答1:
TL;DR
Use dictionary comprehension, like this
>>> my_map = { 'a': ['b', 'c'], 'd': ['e', 'f'] }
>>> {value: key for key in my_map for value in my_map[key]}
{'c': 'a', 'f': 'd', 'b': 'a', 'e': 'd'}
The above seen dictionary comprehension is functionally equivalent to the following looping structure which populates an empty dictionary
>>> inv_map = {}
>>> for key in my_map:
... for value in my_map[key]:
... inv_map[value] = key
...
>>> inv_map
{'c': 'a', 'f': 'd', 'b': 'a', 'e': 'd'}
Note: Using map
shadows the built-in map function. So, don't use that as a variable name unless you know what you are doing.
Other similar ways to do the same
Python 3.x
You can use dict.items, like this
>>> {value: key for key, values in my_map.items() for value in values}
{'c': 'a', 'f': 'd', 'b': 'a', 'e': 'd'}
We use items()
method here, which would create a view object from the dictionary which would give key value pairs on iteration. So we just iterate over it and construct a new dictionary with the inverse mapping.
Python 2.x
You can use dict.iteritems like this
>>> {value: key for key, values in my_map.iteritems() for value in values}
{'c': 'a', 'b': 'a', 'e': 'd', 'f': 'd'}
We don't prefer items()
method in 2.x, because it will return a list of key-value pairs. We don't want to construct a list just to iterate and construct a new dictionary. That is why we prefer iteritems()
, which returns an iterator object which gives a key value pair on iteration.
Note: The actual equivalent of Python 3.x's items
would be Python 2.x's viewitems method, which returns a view object. Read more about the view object in the official documentation, here.
iter*
vs view*
methods in Python 2.x
The main difference between iter*
functions and view*
functions in Python 2.x is that, the view objects reflect the current state of the dictionary. For example,
>>> d = {1: 2}
>>> iter_items = d.iteritems()
>>> view_items = d.viewitems()
now we add a new element to the dictionary
>>> d[2] = 3
If you try to check if (2, 3)
(key-value pair) is in the iter_items
, it will throw an error
>>> (2, 3) in iter_items
Traceback (most recent call last):
File "<input>", line 1, in <module>
RuntimeError: dictionary changed size during iteration
but view object will reflect the current state of the dictionary. So, it will work fine
>>> (2, 3) in view_items
True
回答2:
mp = { 'a': ['b', 'c'], 'd': ['e', 'f'] }
pm={}
for x in mp.iterkeys():
for d in mp[x]:
pm[d]=x
print pm
Output:
{'c': 'a', 'b': 'a', 'e': 'd', 'f': 'd'}
Note: a dictionary is an unordored data structure, so the result may not be ordered as you want it to be.
来源:https://stackoverflow.com/questions/29633848/python-reverse-inverse-a-mapping-but-with-multiple-values-for-each-key