给定这样的字典:
my_map = {'a': 1, 'b': 2}
如何将这张地图倒置即可:
inv_map = {1: 'a', 2: 'b'}
#1楼
这扩展了Robert的答案,适用于字典中的值不是唯一的情况。
class ReversibleDict(dict):
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.iteritems():
revdict.setdefault(v, []).append(k)
return revdict
该实现方式受到限制,因为您不能使用两次reversed
,并且不能将原始操作恢复原状。 因此它不是对称的。 已通过Python 2.6测试。 这是一个我用来打印结果字典的用例。
如果您宁愿使用set
而不是list
,并且可能存在对此有意义的无序应用程序,而不是setdefault(v, []).append(k)
,请使用setdefault(v, set()).add(k)
。
#2楼
除了上面建议的其他功能之外,如果您喜欢lambdas:
invert = lambda mydict: {v:k for k, v in mydict.items()}
或者,您也可以采用这种方式:
invert = lambda mydict: dict( zip(mydict.values(), mydict.keys()) )
#3楼
在保留映射类型的同时执行此操作(假设它是dict
或dict
子类):
def inverse_mapping(f):
return f.__class__(map(reversed, f.items()))
#4楼
另一种更实用的方法:
my_map = { 'a': 1, 'b':2 }
dict(map(reversed, my_map.items()))
#5楼
非双射映射的快速功能解决方案(值不是唯一的):
from itertools import imap, groupby
def fst(s):
return s[0]
def snd(s):
return s[1]
def inverseDict(d):
"""
input d: a -> b
output : b -> set(a)
"""
return {
v : set(imap(fst, kv_iter))
for (v, kv_iter) in groupby(
sorted(d.iteritems(),
key=snd),
key=snd
)
}
从理论上讲,这应该比在命令式解决方案中一个接一个地添加到集合(或追加到列表中)要快。
不幸的是,值必须是可排序的,groupby要求排序。
#6楼
尝试使用python 2.7 / 3.x
inv_map={};
for i in my_map:
inv_map[my_map[i]]=i
print inv_map
#7楼
函数对于类型列表的值是对称的; 执行reverse_dict(reverse_dict(dictionary))时,元组被覆盖到列表中
def reverse_dict(dictionary):
reverse_dict = {}
for key, value in dictionary.iteritems():
if not isinstance(value, (list, tuple)):
value = [value]
for val in value:
reverse_dict[val] = reverse_dict.get(val, [])
reverse_dict[val].append(key)
for key, value in reverse_dict.iteritems():
if len(value) == 1:
reverse_dict[key] = value[0]
return reverse_dict
#8楼
我认为最好的方法是定义一个类。 这是“对称字典”的实现:
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中添加或删除值,并且逆字典将始终保持有效-如果仅对整个字典进行一次反向操作,则情况并非如此。
#9楼
如果值不是唯一的,并且您有点硬核:
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())
)
特别是对于大型dict,请注意,此解决方案的效率远不及Python反向/反转映射的答案,因为它多次遍历items()
。
#10楼
由于字典要求字典中的唯一键与值不同,因此我们必须将反转的值附加到要包含在新特定键中的排序列表中。
def r_maping(dictionary):
List_z=[]
Map= {}
for z, x in dictionary.iteritems(): #iterate through the keys and values
Map.setdefault(x,List_z).append(z) #Setdefault is the same as dict[key]=default."The method returns the key value available in the dictionary and if given key is not available then it will return provided default value. Afterward, we will append into the default list our new values for the specific key.
return Map
#11楼
没有什么完全不同,只是Cookbook重写了一些食谱。 此外,它还通过保留setdefault
方法进行了优化,而不是每次通过实例获取它时:
def inverse(mapping):
'''
A function to inverse mapping, collecting keys with simillar values
in list. Careful to retain original type and to be fast.
>> d = dict(a=1, b=2, c=1, d=3, e=2, f=1, g=5, h=2)
>> inverse(d)
{1: ['f', 'c', 'a'], 2: ['h', 'b', 'e'], 3: ['d'], 5: ['g']}
'''
res = {}
setdef = res.setdefault
for key, value in mapping.items():
setdef(value, []).append(key)
return res if mapping.__class__==dict else mapping.__class__(res)
设计为在CPython 3.x下运行,对于2.x,用mapping.items()
替换mapping.iteritems()
在我的机器上,运行速度比这里的其他示例更快
#12楼
我在循环“ for”和方法“ .get()”的帮助下编写了此文件,并将字典的名称“ map”更改为“ map1”,因为“ map”是一个函数。
def dict_invert(map1):
inv_map = {} # new dictionary
for key in map1.keys():
inv_map[map1.get(key)] = key
return inv_map
#13楼
我们还可以使用defaultdict
反转具有重复键的字典:
from collections import Counter, defaultdict
def invert_dict(d):
d_inv = defaultdict(list)
for k, v in c.items():
d_inv[v].append(k)
return d_inv
text = 'aaa bbb ccc ddd aaa bbb ccc aaa'
c = Counter(text.split()) # Counter({'aaa': 3, 'bbb': 2, 'ccc': 2, 'ddd': 1})
dict(invert_dict(c)) # {1: ['ddd'], 2: ['bbb', 'ccc'], 3: ['aaa']}
看这里 :
与使用
dict.setdefault()
的等效技术相比,此技术更简单,更快。
#14楼
如果值不是唯一的,并且可能是哈希(一维):
for k, v in myDict.items():
if len(v) > 1:
for item in v:
invDict[item] = invDict.get(item, [])
invDict[item].append(k)
else:
invDict[v] = invDict.get(v, [])
invDict[v].append(k)
如果需要更深层次地进行递归,则只需一个维度即可:
def digList(lst):
temp = []
for item in lst:
if type(item) is list:
temp.append(digList(item))
else:
temp.append(item)
return set(temp)
for k, v in myDict.items():
if type(v) is list:
items = digList(v)
for item in items:
invDict[item] = invDict.get(item, [])
invDict[item].append(k)
else:
invDict[v] = invDict.get(v, [])
invDict[v].append(k)
#15楼
这处理非唯一值,并保留了唯一情况的大部分外观。
inv_map = {v:[k for k in my_map if my_map[k] == v] for v in my_map.itervalues()}
对于Python 3.x,将itervalues
替换为values
。
#16楼
我会在python 2中那样做。
inv_map = {my_map[x] : x for x in my_map}
#17楼
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']}
#18楼
def reverse_dictionary(input_dict):
out = {}
for v in input_dict.values():
for value in v:
if value not in out:
out[value.lower()] = []
for i in input_dict:
for j in out:
if j in map (lambda x : x.lower(),input_dict[i]):
out[j].append(i.lower())
out[j].sort()
return out
这段代码是这样的:
r = reverse_dictionary({'Accurate': ['exact', 'precise'], 'exact': ['precise'], 'astute': ['Smart', 'clever'], 'smart': ['clever', 'bright', 'talented']})
print(r)
{'precise': ['accurate', 'exact'], 'clever': ['astute', 'smart'], 'talented': ['smart'], 'bright': ['smart'], 'exact': ['accurate'], 'smart': ['astute']}
#19楼
尝试这个:
inv_map = dict(zip(my_map.values(), my_map.keys()))
(请注意, 字典视图上的Python文档明确保证.keys()
和.values()
的元素顺序相同,这使上述方法可以正常工作。)
或者:
inv_map = dict((my_map[k], k) for k in my_map)
或使用python 3.0的dict理解
inv_map = {my_map[k] : k for k in my_map}
#20楼
假设字典中的值是唯一的:
dict((v, k) for k, v in my_map.iteritems())
#21楼
对于Python 2.7.x
inv_map = {v: k for k, v in my_map.iteritems()}
对于Python 3+:
inv_map = {v: k for k, v in my_map.items()}
#22楼
如果my_map
中的值不是唯一的:
inv_map = {}
for k, v in my_map.iteritems():
inv_map[v] = inv_map.get(v, [])
inv_map[v].append(k)
#23楼
列表和字典理解的结合。 可以处理重复的钥匙
{v:[i for i in d.keys() if d[i] == v ] for k,v in d.items()}
#24楼
例如,您有以下字典:
dict = {'a': 'fire', 'b': 'ice', 'c': 'fire', 'd': 'water'}
而且您想以相反的形式获取它:
inverted_dict = {'fire': ['a', 'c'], 'ice': ['b'], 'water': ['d']}
第一个解决方案 。 要在字典中反转键值对,请使用for
-loop方法:
# Use this code to invert dictionaries that have non-unique values
inverted_dict = dict()
for key, value in 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 dict.items()}
第三解 。 使用还原反转方法(取决于第二种解决方案):
# Use this code to invert dictionaries that have lists of values
dict = {value: key for key in inverted_dict for value in my_map[key]}