词典中的复合键

时间:2013-02-13 01:45:57

标签: python dictionary python-2.7 composite-key

我正在维护一本跟踪对象之间相似性的字典 例如,这个字典可能如下所示:

similarities = {
 p1: {p2: v12, p3:v13, p4:v14},
 p2: {p1: v21, p3:v23, p4:v24},
 p3: {p1: v31, p2:v32, p4:v34},
 p4: {p1: v41, p2:v42, p4:v43}
}

注意,相似性测量是对称的。因此,similarities[p1][p2]similarities[p2][p1]相同,即v12 == v21

有时,我需要从p2中消除similarities[p1];在执行此操作时,我还需要从p1中的所有内部词典中删除p2similarities
这是乏味且低效的。

因此,有没有一种方法可以使用复合键维护字典,而不是维护对称字典,以便查找similarities[p1,p2]

tuple以来我无法真正使用(p1, p2) != (p2, p1),我无法知道如何订购元组。

frozenset是我能想到的唯一其他容器,但不会删除它,因为similarities中可能还有其他键包含p1或{ {1}}作为一个组成部分。那么我可以用什么容器来解决这个问题?

技术信息:

  • python 2.7
  • 此“复合键”中总会有2个元素

谢谢

3 个答案:

答案 0 :(得分:2)

我可能只使用frozenset,假设对象是可清洗的。

或者,如果他们对它们有任何定义明确且一致的顺序,您可以将它们保存在按所述顺序排序的元组中。如果你愿意的话,你可以写一个小的dict子类来透明地为你做这件事。

或者,您可以这样做:

class SymmetricDict(dict):
    def __getitem__(self, key):
        if key in self:
            return dict.__getitem__(self, key)
        a, b = key
        return dict.__getitem__(self, (b, a))

,同样适用于__setitem__

答案 1 :(得分:1)

我认为使用frozenset是唯一合乎逻辑的解决方案。您可以使用具有集合相交测试的理解来找到仅与其中一个值匹配的键:

def remove_ab(ab, similarities):
    return {k:v for k, v in similarities.items() if not ab & k}

similarities = {frozenset({1, 2}): "v12",
                frozenset({1, 3}): "v13",
                frozenset({2, 3}): "v23",
                frozenset({3, 4}): "v34"}

similarities = remove_ab(frozenset({1, 2}), similarities
print(similarities) # output is {frozenset({3, 4}): 'v34'}

答案 2 :(得分:0)

如果p_对象属于支持排序的类型,你可以使用一个元组,其中两个元素总是在lo - >你好吗?