2013-02-13 92 views
2

我正在維護一個字典,用於跟蹤對象之間的相似性。
例如,這本詞典可以是這樣的:字典中的複合鍵

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作爲一個組成部分。那麼我可以用什麼容器來解決這個問題?

技術信息:

  • 蟒蛇2.7
  • 總是會有在這個 「複合鍵」

謝謝

+2

'frozenset'似乎將解決您的問題,我 - 任何理由認爲,有可能是更好的東西? – mgilson 2013-02-13 01:51:16

+0

你可以使用'similarities [p1,p2]'這樣的語法嗎? – Blender 2013-02-13 01:52:10

+0

@Blender:不,這是非法的語法,至多可以翻譯成一個元組 – inspectorG4dget 2013-02-13 01:52:41

回答

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

我可能只用一個確切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__

+0

我想你可能需要'dict .__ getitem __(self,key)'而不是'self [key]'來避免無限循環 – mgilson 2013-02-13 01:56:51

+0

@mgilson當然,我的意思是寫這個,然後我的手指只是輸入了錯誤的東西。 :)修正。 – Dougal 2013-02-13 01:57:30

+0

要「超級」或不要超級......這就是問題...... ;-)。 (就我個人而言,我傾向於不使用'超級') – mgilson 2013-02-13 01:59:11

0

如果P_對象是支持排序的類型,你可以在羅總使用兩個元素的元組 - >喜訂單?

+0

但是這並不能解決刪除所有具有該'p_object'作爲複合組成部分的鍵的問題 – inspectorG4dget 2013-02-13 01:56:34