问题:反转/反转字典映射
给定这样的字典:
my_map = {'a': 1, 'b': 2}
如何将这张地图倒置即可:
inv_map = {1: 'a', 2: 'b'}
回答 0
对于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()}
回答 1
假设字典中的值是唯一的:
dict((v, k) for k, v in my_map.iteritems())
回答 2
如果中的值my_map
不是唯一的:
inv_map = {}
for k, v in my_map.iteritems():
inv_map[v] = inv_map.get(v, [])
inv_map[v].append(k)
回答 3
为此,同时保留映射类型(假设它是a dict
或dict
子类):
def inverse_mapping(f):
return f.__class__(map(reversed, f.items()))
回答 4
尝试这个:
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}
回答 5
另一种更实用的方法:
my_map = { 'a': 1, 'b':2 }
dict(map(reversed, my_map.items()))
回答 6
这扩展了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测试。这是一个我用来打印结果字典的用例。
如果您宁愿使用a而set
不是a list
,并且可能存在对此有意义的无序应用程序,而不是setdefault(v, []).append(k)
use setdefault(v, set()).add(k)
。
回答 7
我们还可以使用重复键反转字典defaultdict
:
from collections import Counter, defaultdict
def invert_dict(d):
d_inv = defaultdict(list)
for k, v in d.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()
。
回答 8
例如,您有以下字典:
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]}
回答 9
列表和字典理解的结合。可以处理重复的钥匙
{v:[i for i in d.keys() if d[i] == v ] for k,v in d.items()}
回答 10
如果值不是唯一的,并且您有点硬核:
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反向/反转映射的答案,因为它会循环items()
多次。
回答 11
除了上面建议的其他功能之外,如果您喜欢lambdas:
invert = lambda mydict: {v:k for k, v in mydict.items()}
或者,您也可以采用这种方式:
invert = lambda mydict: dict( zip(mydict.values(), mydict.keys()) )
回答 12
我认为最好的方法是定义一个类。这是“对称字典”的实现:
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中添加或删除值,并且逆字典将始终保持有效-如果仅对整个字典进行一次反向操作,则情况并非如此。
回答 13
这处理非唯一值,并保留了唯一情况的大部分外观。
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
。
回答 14
函数对于类型列表的值是对称的;执行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
回答 15
由于字典在字典中需要一个与值不同的唯一键,因此我们必须将反转的值附加到要包含在新的特定键中的排序列表中。
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
回答 16
非双射映射的快速功能解决方案(值不是唯一的):
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要求排序。
回答 17
尝试使用python 2.7 / 3.x
inv_map={};
for i in my_map:
inv_map[my_map[i]]=i
print inv_map
回答 18
我会在python 2中那样做。
inv_map = {my_map[x] : x for x in my_map}
回答 19
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’]}
回答 20
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']}
回答 21
没有什么完全不同,只是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()
在我的机器上,运行速度比这里的其他示例更快
回答 22
我在循环“ 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
回答 23
如果值不是唯一的,并且可能是哈希(一维):
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)