【问题标题】:Composite keys in dictionaries字典中的复合键
【发布时间】:2013-01-28 12:04:23
【问题描述】:

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

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

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

那么除了维护对称字典之外,有没有办法用复合键维护字典,以便我可以查找 similarities[p1,p2]

由于(p1, p2) != (p2, p1),我不能真正使用tuple,而且我无法先验地知道如何订购元组。

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

技术信息:

  • python 2.7
  • 这个“复合键”中总是正好有 2 个元素

谢谢

【问题讨论】:

  • frozenset 似乎可以解决您的问题 -- 有什么理由认为可能会有更好的解决方案吗?
  • 你能用similarities[p1, p2]这样的语法吗?
  • 这里的frozenset有什么问题?
  • 也许您对此感兴趣:stackoverflow.com/q/2572916/674039
  • “因为可能还有其他相似的键包含 p1 或 p2 作为组件” - 如果您的意思是您将同时拥有 frozenset({p1, p2})frozenset({p1, p3}),我没有看看这是怎么回事。否则我想我不明白你的解释。

标签: python dictionary python-2.7 composite-key


【解决方案1】:

假设对象是可散列的,我可能只使用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__ 也是如此。

【讨论】:

  • 我认为您可能需要dict.__getitem__(self,key) 而不是self[key] 以避免无限循环
  • @mgilson 当然,我是想写那个,然后我的手指就打错了。 :) 已修复。
  • super 还是不到super ...这是个问题... ;-)。 (就我个人而言,我倾向于不使用super
【解决方案2】:

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

【讨论】:

  • 但这并不能解决删除所有具有 p_object 的键作为组合的一部分的问题
【解决方案3】:

我认为使用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'}

【讨论】:

    猜你喜欢
    • 2011-02-22
    • 1970-01-01
    • 1970-01-01
    • 2014-09-04
    • 1970-01-01
    • 2016-09-26
    • 1970-01-01
    • 1970-01-01
    • 2012-05-26
    相关资源
    最近更新 更多