Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 反转/反转字典映射_Python_Dictionary_Mapping_Reverse - Fatal编程技术网

Python 反转/反转字典映射

Python 反转/反转字典映射,python,dictionary,mapping,reverse,Python,Dictionary,Mapping,Reverse,如果有这样一本字典: my_map = {'a': 1, 'b': 2} 如何反转此贴图以获得: inv_map = {1: 'a', 2: 'b'} 试试这个: inv_map = dict(zip(my_map.values(), my_map.keys())) (请注意,明确保证.keys()和.values()的元素顺序相同,这允许上述方法工作。) 或者: inv_map = dict((my_map[k], k) for k in my_map) 或者使用python 3.0的

如果有这样一本字典:

my_map = {'a': 1, 'b': 2}
如何反转此贴图以获得:

inv_map = {1: 'a', 2: 'b'}
试试这个:

inv_map = dict(zip(my_map.values(), my_map.keys()))
(请注意,明确保证
.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}

假设dict中的值是唯一的:

dict((v, k) for k, v in my_map.iteritems())
Python 3+:

inv_map = {v: k for k, v in my_map.items()}
Python 2:

inv_map = {v: k for k, v in my_map.iteritems()}

如果
my_map
中的值不唯一:

inv_map = {}
for k, v in my_map.iteritems():
    inv_map[v] = inv_map.get(v, []) + [k]

要在保留映射类型的同时执行此操作(假设它是
dict
dict
子类):


如果这些价值观不是独一无二的,而你又有点顽固:

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,请注意此解决方案的效率远远低于答案,因为它会多次循环
项()

这将扩展答案,适用于dict中的值不唯一的情况

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
该实现的局限性在于,您不能使用
反向
两次并取回原始版本。它本身不是对称的。它是用Python2.6测试的。是我如何使用打印结果dict的用例


如果您更喜欢使用
集合
而不是
列表
,并且可能存在对其有意义的无序应用程序,而不是
setdefault(v,[])。附加(k)
,请使用
setdefault(v,set())。除了上面建议的其他函数之外,如果您喜欢lambdas,还可以添加(k)

invert=lambda mydict:{v:k代表k,v代表mydict.items()}
或者,你也可以这样做:

invert=lambda mydict:dict(zip(mydict.values(),mydict.keys())

另一种更实用的方式:

my_map = { 'a': 1, 'b':2 }
dict(map(reversed, my_map.items()))

非双射映射的快速函数解决方案(值不唯一):

从理论上讲,这应该比一个接一个地添加到集合(或添加到列表)要快,就像在中一样


不幸的是,这些值必须是可排序的,groupby需要排序。

请在python 2.7/3.x中尝试此方法

inv_map={};
for i in my_map:
    inv_map[my_map[i]]=i    
print inv_map

函数对于类型列表的值是对称的;在执行reverse_dict(reverse_dict(dictionary))时,元组被转换为列表


我认为最好的方法是定义一个类。下面是一个“对称字典”的实现:

如果需要,删除和迭代方法很容易实现


此实现比反转整个字典(这似乎是本页上最流行的解决方案)更有效。更不用说,您可以随意添加或删除符号中的值,而反向字典将始终保持有效——如果您只需将整个字典反转一次,则情况并非如此。

因为字典需要字典中的一个唯一键,而不是值,我们必须将反转的值附加到排序列表中,以包含在新的特定键中

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

不是完全不同的东西,只是从食谱中改写了一点。通过保留
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.iterms()


在我的机器上运行得比这里的其他示例快一些

我在cycle'for'和method.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

我们还可以使用
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()
的等效技术更简单、更快


如果值不是唯一的并且可能是散列(一维):

如果需要更深入地挖掘,则使用递归,然后仅使用一维:

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)

这将处理非唯一值,并保留唯一案例的大部分外观

inv_map = {v:[k for k in my_map if my_map[k] == v] for v in my_map.itervalues()}

对于Python3.x,将
itervalues
替换为

在Python2中,我会这样做

inv_map = {my_map[x] : x for x in my_map}
这将提供如下输出:{1:['a',d'],2:['b'],3:['c']}

  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']}
{'c': '1',
 'b': '1',
 'a': '1',
 'f': '2',
 'd': '2',
 'e': '2',
 'g': '3',
 'h': '3',
 'i': '3'}

列表和词典理解的结合。可以处理重复的密钥

{v:[i for i in d.keys() if d[i] == v ] for k,v in d.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
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 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()}
第三种解决方案。使用反转方法(依赖于第二种解决方案):


针对当前python 3.x版本的lambda解决方案:

d1 = dict(alice='apples', bob='bananas')
d2 = dict(map(lambda key: (d1[key], key), d1.keys()))
print(d2)
结果:

{'apples': 'alice', 'bananas': 'bob'}
此解决方案不检查重复项

一些评论:

  • lambda构造可以从外部作用域访问d1,因此我们仅 传入当前键。它返回一个元组
  • dict()构造函数接受元组列表。信息技术 还接受映射的结果,因此我们可以跳过转换到 名单
  • 此解决方案没有显式的
    for
    循环。它还避免了对数学不好的人使用
    列表理解;-)
    
我发现这个版本比公认的10000键字典快10%以上

d = {i: str(i) for i in range(10000)}

new_d = dict(zip(d.values(), d.keys()))

这里有另一种方法

my_map = {'a': 1, 'b': 2}

inv_map= {}
for key in my_map.keys() :
    val = my_map[key]
    inv_map[val] = key

字典值为集合的情况。比如:

some_dict = {"1":{"a","b","c"},
        "2":{"d","e","f"},
        "3":{"g","h","i"}}
相反,我希望:

some_dict = {vi: k  for k, v in some_dict.items() for vi in v}
输出如下:

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']}
{'c': '1',
 'b': '1',
 'a': '1',
 'f': '2',
 'd': '2',
 'e': '2',
 'g': '3',
 'h': '3',
 'i': '3'}

我知道这个问题已经有了很多很好的答案,但我想与大家分享一个非常简洁的解决方案,该解决方案还考虑了重复值:

def dict_reverser(d):
    seen = set()
    return {v: k for k, v in d.items() if v not in seen or seen.add(v)}

这取决于这样一个事实,即在Python中,
set.add
总是返回
None

很多答案,但在我们谈论的具有非唯一值的字典时,没有找到任何干净的答案

解决办法是:

from collections import defaultdict

inv_map = defaultdict(list) 
for k, v in my_map.items(): 
    inv_map[v].append(k)
Examp
{'c': '1',
 'b': '1',
 'a': '1',
 'f': '2',
 'd': '2',
 'e': '2',
 'g': '3',
 'h': '3',
 'i': '3'}
def dict_reverser(d):
    seen = set()
    return {v: k for k, v in d.items() if v not in seen or seen.add(v)}
from collections import defaultdict

inv_map = defaultdict(list) 
for k, v in my_map.items(): 
    inv_map[v].append(k)
{5: ['a', 'd'], 1: ['c'], 10: ['b']}