4

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

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}
}

请注意,相似度测量是对称的。因此,与iesimilarities[p1][p2]相同。similarities[p2][p1]v12 == v21

有时,我需要p2消除similarities[p1]; 在这样做的过程中,我还需要从所有内部字典中删除p1和。 这是乏味和低效的。p2similarities

所以不是维护一个对称字典,有没有办法用一个复合键来维护一个字典,以便我可以查找similarities[p1,p2]

我真的不能使用,tuple因为(p1, p2) != (p2, p1)我不能先验地知道如何订购元组。

Afrozenset是我能想到的唯一其他容器,但这不会削减它,因为其中可能还有其他键similarities包含其中一个p1p2作为一个组件。那么我可以使用什么容器来解决这个问题呢?

技术信息:

  • 蟒蛇2.7
  • 这个“复合键”中总会有两个元素

谢谢

4

3 回答 3

2

frozenset假设对象是可散列的,我可能只使用 a 。

或者,如果它们有任何定义明确且一致的顺序,您可以将它们保存在按所述顺序排序的元组中。如果你愿意,你可以编写一个小子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__.

于 2013-02-13T01:51:53.967 回答
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'}
于 2013-02-13T02:21:06.087 回答
0

如果 p_ 对象属于支持排序的类型,您是否可以使用两个元素始终处于 lo --> hi 顺序的元组?

于 2013-02-13T01:53:32.667 回答