python可逆字典

python可逆字典,python,dictionary,hashtable,Python,Dictionary,Hashtable,我想以类似于字典的形式在Python中存储一些数据:{1:'a',2:'b'}。每个值都是唯一的,不仅在其他值之间,而且在键之间也是唯一的 是否有一个简单的数据结构,无论我使用“键”还是“值”,都可以用来获取相应的对象?例如: >>> a = {1:'a', 2:'b'} >>> a[1] 'a' >>> a['b'] 2 >>> a[3] KeyError “键”是标准的python int,值很短(相关帖子: 当然

我想以类似于字典的形式在Python中存储一些数据:
{1:'a',2:'b'}
。每个值都是唯一的,不仅在其他值之间,而且在键之间也是唯一的

是否有一个简单的数据结构,无论我使用“键”还是“值”,都可以用来获取相应的对象?例如:

>>> a = {1:'a', 2:'b'}
>>> a[1]
'a'
>>> a['b']
2
>>> a[3]
KeyError
“键”是标准的python int,值很短(相关帖子:

当然,如果所有的值和键都是唯一的,难道你不能只使用一个字典,并在开始时同时插入key:value和value:key吗

a = {1:'a', 2:'b'}
a.update(dict((v, k) for k, v in a.iteritems()))
然后,您将能够根据需要同时执行这两项操作:

print a[1]
print a['a']

如果键和值不重叠,一个明显的方法是将它们存储在同一个目录中,即:

class BidirectionalDict(dict):
    def __setitem__(self, key, val):
        dict.__setitem__(self, key, val)
        dict.__setitem__(self, val, key)

    def __delitem__(self, key):
        dict.__delitem__(self, self[key])
        dict.__delitem__(self, key)

d = BidirectionalDict()
d['foo'] = 4
print d[4]   # Prints 'foo'
(您可能还希望实现类似于
\uuuu init\uuuuu
更新
iter*
方法的功能,以像真正的dict一样工作,这取决于您需要多少功能)

这应该只涉及一次查找,虽然可能不会为您节省太多内存(毕竟您的dict条目数仍然是原来的两倍)。但是请注意,无论是这项查找还是原始查找都不会占用两倍的空间:dict只占用引用的空间(实际上是指针),再加上过度分配的开销。由于指向相同的对象,数据本身占用的空间不会重复两次。

这里使用的是用户定义的类

而代码

# search a dictionary for key or value
# using named functions or a class
# tested with Python25 by Ene Uran 01/19/2008

def find_key(dic, val):
    """return the key of dictionary dic given the value"""
    return [k for k, v in symbol_dic.iteritems() if v == val][0]

def find_value(dic, key):
    """return the value of dictionary dic given the key"""
    return dic[key]

class Lookup(dict):
    """
    a dictionary which can lookup value by key, or keys by value
    """
    def __init__(self, items=[]):
        """items can be a list of pair_lists or a dictionary"""
        dict.__init__(self, items)

    def get_key(self, value):
        """find the key(s) as a list given a value"""
        return [item[0] for item in self.items() if item[1] == value]

    def get_value(self, key):
        """find the value given a key"""
        return self[key]

在计算机编程的艺术中,Vokume 3 Knuth有一个关于辅助键查找的部分。就您的问题而言,该值可以被视为辅助键

第一个建议是执行您已经完成的操作:按值对键进行有效的索引

第二个建议是设置一个大型btree,它是聚集数据的复合索引,其中分支节点包含值,叶子包含键数据和指向较大记录的指针(如果有)

如果数据是几何的(就像你看起来的那样),那么就有所谓的邮局树。它可以回答这样的问题:离x点最近的对象是什么。这里有几个例子:这种查询的另一个简单选项是四叉树和k-d树

最后一个选择是组合散列,将键和值组合成一种特殊的散列,即使没有这两个值,也可以对散列进行有效的查找。我在网上找不到一个好的组合散列解释,但它在TAoCP第三卷第二版573页


当然,对于其中的一些,您可能需要编写自己的代码。但是,如果内存或性能确实是关键,您可能需要花时间。

它不应该使用“两倍的空间”.字典只存储对数据的引用,而不是数据本身。因此,如果有一百万个字符串占用十亿字节,那么每个字典可能需要额外的1000-2000万字节,这只是整个存储的一小部分。使用两个字典是正确的做法。

我已经这样做很多年了。我个人与其他解决方案相比,我更喜欢它的简单性

d = {1: 'a', 2: 'b'}
dict(zip(d.values(), d.keys()))

在您的示例中,您真的是指a[1]返回“1”吗?似乎您希望它返回“a”。(0)点与.key()相反?--请复制/粘贴实际工作代码(1)平均查找次数应为N*(2-p),其中p=prob(在第1条中找到);“50%较慢”表示p很小,或者您引入了开销(2)除非你做了一些特别的事情,否则你的字符串不会被复制,所以你的内存使用不会翻倍你怎么会不知道你有一个int对象还是str对象?是的,如果所有的键和值都是唯一的,你/可以/使用一个字典。没有想到这一点。+1他可以,取决于他想做什么…例如,single_dict.items()和friends可能会导致问题和/或过度使用isinstance()但是在这种情况下,你不能直接访问一个值,因为你需要寻找它。它降低了字典的兴趣
d = {1: 'a', 2: 'b'}
dict(zip(d.values(), d.keys()))