互换词典

Interchangeable dictionary

我希望有一个可互换的字典,即值与键映射,键与值映射,这样如果我们知道一个元素,就可以知道另一个伙伴。在 python dict 中,使用键,我们可以获得值,但反之亦然。我怎样才能做到这一点? 注意:为了可互换性,key: value & value: key 之间必须存在 1-1 映射。

示例:

key = {'a':'1','b':'2','c':'3'}
So, I should be able to get 1 for key['a'] & 'a' for key['1']

一种可能的方法是...您可以简单地更新现有字典,因为它包含所有相反的 key-value 对,如下所示:

dict1 = {'a': '1','b' :'2','c': '3'}
dict2 = dict(zip(dict1.values(), dict1.keys())) # create value-key pair dictionary

dict1.update(dict2) # combining dict2 with dict1
print(dict1)
#{'a': '1', 'b': '2', 'c': '3', '1': 'a', '2': 'b', '3': 'c'}

但是,您应该小心使用它,因为可能存在重复的键和值。

假设永远不会发生碰撞(即键和值是不相交的集合),那么您可以创建“镜像”dict,然后按如下方式利用 collections.ChainMap

import collections
key = {'a':'1','b':'2','c':'3'}
rev_key = dict(i[::-1] for i in key.items())
final = collections.ChainMap(key,rev_key)
print(final['a'])
print(final['3'])
print(final['c'])

输出

1
c
3

警告:此解决方案假定您只想使用 final 进行阅读。它不支持反映您插入的值(例如 final['d'] = '4' 不会导致 final['4'] 变为 'd'

这是一个示例,说明您可以如何创建一个 class 来为您执行此操作。请注意,这在设置新值/编辑现有值时非常慢。

class DoubleDict:
    def __init__(self, *dicts, **extras):
        self.dict1 = {}
        for dct in dicts:
            self.dict1 |= dct
        self.dict1 |= extras
        self.dict2 = dict(zip(self.dict1.values(), self.dict1.keys()))
    def __getitem__(self, key):
        try: return self.dict1.__getitem__(key)
        except KeyError: return self.dict2.__getitem__(key)
    def __setitem__(self, key, value):
        if key in self.dict1:
            self.dict2.pop(self.dict1[key])
            self.dict1.pop(key)
        elif key in self.dict2:
            self.dict1.pop(self.dict2[key])
            self.dict2.pop(key)
        if value in self.dict1:
            self.dict2.pop(self.dict1[value])
            self.dict1.pop(value)
        elif value in self.dict2:
            self.dict1.pop(self.dict2[value])
            self.dict2.pop(value)
        self.dict1[key] = value
        self.dict2[value] = key
    def __iter__(self):
        total_dict = self.dict1 | self.dict2
        return total_dict.__iter__()
    def __repr__(self):
        return f"DoubleDict({repr(self.dict1)})"
    def __str__(self):
        return "\n".join(f"{key}  <==>  {self.dict1[key]}" for key in self.dict1)

工作原理如下:

a = DoubleDict({1: 2, 3: 4, 5: 6, 7: 8})
print(a)
# 1  <==>  2
# 3  <==>  4
# 5  <==>  6
# 7  <==>  8
a[1] = 3
# Now the 3,4 pair and the 1,2 pair no longer exist, but there is a new 3,1 pair
print(a[1], a[3])
# 3 1
print(a)
# 5  <==>  6
# 7  <==>  8
# 1  <==>  3