给定一本这样的字典:
my_map = {'a': 1, 'b': 2}
如何将此映射颠倒得到:
inv_map = {1: 'a', 2: 'b'}
给定一本这样的字典:
my_map = {'a': 1, 'b': 2}
如何将此映射颠倒得到:
inv_map = {1: 'a', 2: 'b'}
当前回答
例如,你有以下字典:
my_dict = {'a': 'fire', 'b': 'ice', 'c': 'fire', 'd': 'water'}
你想要得到这样一个倒立的形式
inverted_dict = {'fire': ['a', 'c'], 'ice': ['b'], 'water': ['d']}
第一个解决方案。要在字典中反转键值对,请使用For循环方法:
# Use this code to invert dictionaries that have non-unique values
inverted_dict = dict()
for key, value in my_dict.items():
inverted_dict.setdefault(value, list()).append(key)
第二个解决方案。使用字典理解方法进行反转:
# Use this code to invert dictionaries that have unique values
inverted_dict = {value: key for key, value in my_dict.items()}
第三个解决方案。使用反转方法(依赖于第二个解决方案):
# Use this code to invert dictionaries that have lists of values
my_dict = {value: key for key in inverted_dict for value in my_map[key]}
其他回答
如果值不是唯一的,并且你有点硬核:
inv_map = dict(
(v, [k for (k, xx) in filter(lambda (key, value): value == v, my_map.items())])
for v in set(my_map.values())
)
特别是对于大型字典,请注意,此解决方案的效率远远低于Python reverse / invert映射的答案,因为它在items()上循环多次。
我认为最好的方法是定义一个类。下面是一个“对称字典”的实现:
class SymDict:
def __init__(self):
self.aToB = {}
self.bToA = {}
def assocAB(self, a, b):
# Stores and returns a tuple (a,b) of overwritten bindings
currB = None
if a in self.aToB: currB = self.bToA[a]
currA = None
if b in self.bToA: currA = self.aToB[b]
self.aToB[a] = b
self.bToA[b] = a
return (currA, currB)
def lookupA(self, a):
if a in self.aToB:
return self.aToB[a]
return None
def lookupB(self, b):
if b in self.bToA:
return self.bToA[b]
return None
如果需要,删除和迭代方法很容易实现。
这种实现比颠倒整个字典(这似乎是本页上最流行的解决方案)更有效。更不用说,您可以随心所欲地从SymDict中添加或删除值,并且您的反向字典将始终保持有效——如果您只是将整个字典反向一次,这是不正确的。
当前python 3的lambda解决方案。x版本:
d1 = dict(alice='apples', bob='bananas')
d2 = dict(map(lambda key: (d1[key], key), d1.keys()))
print(d2)
结果:
{'apples': 'alice', 'bananas': 'bob'}
此解决方案不检查重复项。
一些评论:
构造可以从外部作用域访问d1,所以我们只能 传入当前键。它返回一个元组。 dict()构造函数接受一个元组列表。它 也接受映射的结果,所以我们可以跳过转换到 列表。 这个解决方案没有显式的for循环。它还避免了对那些数学不好的人使用列表理解;-)
这扩展了Robert的回答,适用于字典中的值不是唯一的情况。
class ReversibleDict(dict):
# Ref: https://stackoverflow.com/a/13057382/
def reversed(self):
"""
Return a reversed dict, with common values in the original dict
grouped into a list in the returned dict.
Example:
>>> d = ReversibleDict({'a': 3, 'c': 2, 'b': 2, 'e': 3, 'd': 1, 'f': 2})
>>> d.reversed()
{1: ['d'], 2: ['c', 'b', 'f'], 3: ['a', 'e']}
"""
revdict = {}
for k, v in self.items():
revdict.setdefault(v, []).append(k)
return revdict
该实现的局限性在于您不能使用反转两次并获得原始数据。它本身不是对称的。它是用Python 2.6测试的。这是一个用例,我是如何使用打印结果字典。
如果你更喜欢使用集合而不是列表,并且可能存在无序的应用程序,这是有意义的,而不是setdefault(v, []).append(k),使用setdefault(v, set()).add(k)。
def invertDictionary(d):
myDict = {}
for i in d:
value = d.get(i)
myDict.setdefault(value,[]).append(i)
return myDict
print invertDictionary({'a':1, 'b':2, 'c':3 , 'd' : 1})
这将提供输出为:{1:(' a ', ' d '), 2: [b], 3: [' c ']}