Python反向/反转映射

Bri*_*unt 597 python mapping reverse dictionary

给出这样的字典:

my_map = {'a': 1, 'b': 2}
Run Code Online (Sandbox Code Playgroud)

如何反转此地图以获得:

inv_map = {1: 'a', 2: 'b'}
Run Code Online (Sandbox Code Playgroud)

编者注: __CODE__改为__CODE__避免与内置函数冲突,__CODE__.下面有些评论可能会受到影响.

Sil*_*ost 825

对于Python 2.7.x

inv_map = {v: k for k, v in my_map.iteritems()}
Run Code Online (Sandbox Code Playgroud)

对于Python 3+:

inv_map = {v: k for k, v in my_map.items()}
Run Code Online (Sandbox Code Playgroud)

  • 除非如果值中没有单一性,否则它将无效.在这种情况下,你会丢失一些条目 (13认同)
  • **有趣的事实:**[字典将在Python 3.7开始时订购(在插入时)](/sf/ask/2798622641/) . (10认同)
  • @Mattias,对于Python 3.6来说是这样。对于3.7版,正式保留订单:https://mail.python.org/pipermail/python-dev/2017-December/151283.html。BDFL是这样说的。 (7认同)
  • 是的,作为实现细节。`这个新实现的顺序保留方面被认为是一个实现细节,不应依赖`。不能保证它会保持这种状态,所以不要编写依赖于具有与 OrderedDict 相同行为的 Dict 的代码。 (4认同)
  • 在最近的Python 2.7.x版本中,`my_map.items()`也可以 (3认同)
  • @valentin是的,那*有效*,但效率较低,因为它生成一个对列表,而不是一个迭代器。 (2认同)

小智 168

假设dict中的值是唯一的:

dict((v, k) for k, v in my_map.iteritems())
Run Code Online (Sandbox Code Playgroud)

  • @ Buttons840:如果值不是唯一的,那么无论如何都没有字典的唯一反转,换句话说,反转没有意义. (28认同)
  • 这些值也必须是可以清洗的 (16认同)
  • @Wrzlprmft对于非唯一值,有一个自然的inverse定义.每个值都映射到通向它的键集. (4认同)
  • @ Buttons840只显示该值的最后一个键.可能无法保证`iteritems()`将输出的顺序,因此可以假设将为非唯一值分配任意键,其方式在某些条件下显然是可重现的,但是没有所以总的来说. (2认同)
  • 请注意,当然,在 Python 3 中不再有 `iteritems()` 方法,这种方法将不起作用;使用`items()`代替,如已接受的答案所示。此外,字典理解会使这比调用“dict”更漂亮。 (2认同)

Rob*_*ney 121

如果值my_map不是唯一的:

inv_map = {}
for k, v in my_map.iteritems():
    inv_map[v] = inv_map.get(v, [])
    inv_map[v].append(k)
Run Code Online (Sandbox Code Playgroud)

  • ...或者只是inv_map.setdefault(v,[]).append(k).我曾经是一个默认的狂热粉丝,但后来我搞了很多次并得出结论,实际上明确比隐含更好. (53认同)
  • 一套在这里会更有意义.钥匙(可能)可以清洗,没有订单.`inv_map.setdefault(v,set()).add(k)`. (9认同)
  • 在python3中,使用`my_map.items()`代替`my_map.iteritems()`。 (5认同)
  • @YaroslavBulatov 不,此处显示的代码没有损坏 - `inv_map.get(v, [])` 返回已添加的列表(如果有),因此分配不会重置为空列表。不过,“setdefault”仍然会更漂亮。 (2认同)
  • 您可以通过使用“defaultdict”来避免“setdefault”:“inv_map = collections.defaultdict(set)”,然后简单地使用“inv_map[v].add(k)” (2认同)

fs.*_*fs. 41

def inverse_mapping(f):
    return f.__class__(map(reversed, f.items()))
Run Code Online (Sandbox Code Playgroud)

  • @Rafael_Espericueta 对于这个问题的任何可能的答案都是如此,因为具有重复值的地图是不可逆的。 (5认同)
  • 可能很聪明,但是当原始字典中有多个键具有相同的值时,它将不起作用。 (3认同)
  • 我认为没有必要执行 `f.__class__` 因为您已经假设它是一本字典。我会这样做:`dict(map(reversed, f.items()))` (3认同)
  • @Mark_Amery 从某种意义上来说,它可以更普遍地是可逆的。例如:D = {1: [1, 2], 2:[2, 3], 3: [1]}, Dinv = {1: [1, 3], 2: [1, 2], 3: [2]}。D是例如{parent:children}的字典,而Dinv是字典{child:parents}。 (2认同)

syk*_*ora 32

试试这个:

inv_map = dict(zip(my_map.values(), my_map.keys()))
Run Code Online (Sandbox Code Playgroud)

(请注意,字典视图上的Python文档明确保证.keys()并且.values()它们的元素具有相同的顺序,这允许上述方法起作用.)

或者:

inv_map = dict((my_map[k], k) for k in my_map)
Run Code Online (Sandbox Code Playgroud)

或使用python 3.0的字典理解

inv_map = {my_map[k] : k for k in my_map}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这仅在键是唯一的情况下才有效(如果您想反转它们,则几乎不会出现这种情况)。 (3认同)

Bre*_*ire 22

另一种更实用的方式:

my_map = { 'a': 1, 'b':2 }
dict(map(reversed, my_map.items()))
Run Code Online (Sandbox Code Playgroud)

  • 谢谢发帖.我不确定这是否可取 - 在PEP 279中引用Guido Van Rossum:"过滤器`和`map`应该会死并被归入列表理解中,而不是增加更多的变体". (2认同)
  • 是的,布莱恩是个公平点。我只是将其添加为对话点。dict理解方法在我想像的大多数情况下更具可读性。(而且我猜可能还会更快) (2认同)
  • 可能不如其他可读性更好,但是这种方式的好处是能够将“ dict”与其他映射类型(例如“ collections.OrderedDict”或“ collections.defaultdict”)交换出去。 (2认同)

小智 11

字典值是集合的情况。喜欢:

some_dict = {"1":{"a","b","c"},
        "2":{"d","e","f"},
        "3":{"g","h","i"}}
Run Code Online (Sandbox Code Playgroud)

逆函数会喜欢:

some_dict = {vi: k  for k, v in some_dict.items() for vi in v}
Run Code Online (Sandbox Code Playgroud)

输出是这样的:

{'c': '1',
 'b': '1',
 'a': '1',
 'f': '2',
 'd': '2',
 'e': '2',
 'g': '3',
 'h': '3',
 'i': '3'}
Run Code Online (Sandbox Code Playgroud)


Ani*_*non 11

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

解决方案是:

from collections import defaultdict

inv_map = defaultdict(list) 
for k, v in my_map.items(): 
    inv_map[v].append(k)
Run Code Online (Sandbox Code Playgroud)

例子:

如果初始字典my_map = {'c': 1, 'd': 5, 'a': 5, 'b': 10}

然后,运行上面的代码将给出:

{5: ['a', 'd'], 1: ['c'], 10: ['b']}
Run Code Online (Sandbox Code Playgroud)


Acu*_*nus 9

这扩展了Python反向/反转映射的答案,适用于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
Run Code Online (Sandbox Code Playgroud)

实施是有限的,你不能使用reversed两次并获得原来的.它不是对称的.它使用Python 2.6进行测试.是我用于打印结果字典的用例.

如果您更愿意使用a而set不是a list,并且有些应用程序对此有意义,而不是setdefault(v, []).append(k)使用setdefault(v, set()).add(k).


iru*_*yak 8

我们还可以使用来重复键重复的字典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']}  
Run Code Online (Sandbox Code Playgroud)

这里

与使用的等效技术相比,此技术更简单,更快dict.setdefault()


ARG*_*Geo 6

例如,您有以下字典:

dict = {'a': 'fire', 'b': 'ice', 'c': 'fire', 'd': 'water'}
Run Code Online (Sandbox Code Playgroud)

你想以这样的倒置形式得到它:

inverted_dict = {'fire': ['a', 'c'], 'ice': ['b'], 'water': ['d']}
Run Code Online (Sandbox Code Playgroud)

第一个解决方案。要反转字典中的键值对,请使用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)
Run Code Online (Sandbox Code Playgroud)

第二个解决方案。使用字典理解方法进行反演:

# Use this code to invert dictionaries that have unique values

inverted_dict = {value: key for key, value in dict.items()}
Run Code Online (Sandbox Code Playgroud)

第三个解决方案。使用反转反转方法(依赖于第二种解决方案):

# 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]}
Run Code Online (Sandbox Code Playgroud)

  • `dict` 是保留的,不应该用于变量名 (4认同)
  • 忘记告诉我们`my_map`是什么 (2认同)

小智 5

列表与字典理解的结合.可以处理重复的键

{v:[i for i in d.keys() if d[i] == v ] for k,v in d.items()}
Run Code Online (Sandbox Code Playgroud)

  • 就像 /sf/answers/2930270521/ 一样,这是一个 O(n²) 解决方案,可以通过几行额外的代码在 O(n) 中轻松解决。 (2认同)