我在python中創建了一個算法,用於爲值對創建度量,其中m(v1, v2) == m(v2, v1)
(即它是對稱的)。我的想法是編寫一本字典詞典,其中這些值以有效的內存方式存儲,以便可以按任意順序輕鬆檢索這些值。我喜歡繼承東西,理想情況下,我喜歡寫一個symmetric_dict
,其中s_d[v1][v2]
總是等於s_d[v2][v1]
,可能是通過根據某種排序關係檢查哪個v更大,然後切換它們以便更小的元素首先總是提到一個。即當撥打s_d[5][2] = 4
時,字典的字典會將它們翻轉,使得它們實際上被存儲爲s_d[2][5] = 4
,並且對於數據的檢索是相同的。 我對於更好的數據結構也非常開放,但我更喜歡一個帶有「is-a」關係的實現,它只是使用字典並預處理一些函數參數。對稱字典其中d [a] [b] == d [b] [a]
3
A
回答
2
這是一個看起來很有前途的略有不同的方法。儘管SymDict
類不是dict
子類,但其大部分行爲類似於一個,並且只涉及單個私有字典。我認爲一個有趣的功能是它保留了您似乎想要的自然[][]
查找語法。
class SymDict(object):
def __init__(self, *args, **kwrds):
self._mapping = _SubSymDict(*args, **kwrds)
def __getitem__(self, key1):
self._mapping.set_key1(key1)
return self._mapping
def __setitem__(self, key1, value):
raise NotImplementedError
def __str__(self):
return '_mapping: ' + self._mapping.__str__()
def __getattr__(self, name):
return getattr(self._mapping, name)
class _SubSymDict(dict):
def __init__(self, *args, **kwrds):
dict.__init__(self, *args, **kwrds)
def set_key1(self, key1):
self.key1 = key1
def __getitem__(self, key2):
return dict.__getitem__(self, frozenset((self.key1, key2)))
def __setitem__(self, key2, value):
dict.__setitem__(self, frozenset((self.key1, key2)), value)
symdict = SymDict()
symdict[2][4] = 24
symdict[4][2] = 42
print 'symdict[2][4]:', symdict[2][4]
# symdict[2][4]: 42
print 'symdict[4][2]:', symdict[4][2]
# symdict[4][2]: 42
print 'symdict:', symdict
# symdict: _mapping: {frozenset([2, 4]): 42}
print symdict.keys()
# [frozenset([2, 4])]
3
如圖所示,使用嵌套索引來做它將會非常困難。相反,最好使用元組作爲關鍵字。這樣可以對元組進行排序,並且可以訪問封裝的dict
以獲取該值。
d[2, 5] = 4
print d[5, 2]
1
一個明顯的替代方法是使用一個(v1,v2)
元組作爲密鑰到一個單一的標準dict
,並插入兩個(v1,v2)
和(v2,v1)
到字典,使得它們指代相同的對象在右手側。
11
你可以使用一個frozenset
爲您的字典的關鍵是:
>>> s_d = {}
>>> s_d[frozenset([5,2])] = 4
>>> s_d[frozenset([2,5])]
4
這將是相當簡單的寫的dict
一個子類,把iterables關鍵參數,然後轉身然後進入一個frozenset
存儲值時, :
class SymDict(dict):
def __getitem__(self, key):
return dict.__getitem__(self, frozenset(key))
def __setitem__(self, key, value):
dict.__setitem__(self, frozenset(key), value)
它給你:
>>> s_d = SymDict()
>>> s_d[5,2] = 4
>>> s_d[2,5]
4
2
正如替代戴夫·韋伯的frozenset,爲什麼不做一個SymDict如下所示:
class SymDict(dict):
def __getitem__(self, key):
return dict.__getitem__(self, key if key[0] < key[1] else (key[1],key[0]))
def __setitem__(self, key, value):
dict.__setitem__(self, key if key[0] < key[1] else (key[1],key[0]), value)
從一個簡單的測試,這是用於獲取和設置項比使用frozenset速度超過10%。無論如何,只是另一個想法。但是,它的適應性不如凍結集,因爲它實際上只能用於長度爲2的元組。據我從OP可以看出,這似乎並不是一個問題。
2
提高對賈斯汀·皮爾的解決方案,你需要添加__delitem__
和__contains__
方法幾個字典操作工作。所以,完整性,
class SymDict(dict):
def __getitem__(self, key):
return dict.__getitem__(self, key if key[0] < key[1] else (key[1],key[0]))
def __setitem__(self, key, value):
dict.__setitem__(self, key if key[0] < key[1] else (key[1],key[0]), value)
def __delitem__(self, key):
return dict.__delitem__(self, key if key[0] < key[1] else (key[1],key[0]))
def __contains__(self, key):
return dict.__contains__(self, key if key[0] < key[1] else (key[1],key[0]))
所以後來
>>> s_d = SymDict()
>>> s_d[2,5] = 4
>>> s_d[5,2]
4
>>> (5,2) in s_d
True
>>> del s_d[5,2]
>>> s_d
{}
我不知道,不過,是否涵蓋所有的基礎,但它是爲我自己的代碼不夠好。
1
我想提取功能更可讀性(對於patvarilly答案)
class SymDict(dict):
def __getitem__(self, key):
return dict.__getitem__(self, self.symm(key))
def __setitem__(self, key, value):
dict.__setitem__(self, self.symm(key), value)
def __delitem__(self, key):
return dict.__delitem__(self, self.symm(key))
def __contains__(self, key):
return dict.__contains__(self, self.symm(key))
@staticmethod
def symm(key):
return key if key[0] < key[1] else (key[1], key[0]).
相關問題
- 1. 如何寫A :: B :: C => D給定A :: B :: C和(A,B,C)=> D?
- 2. SQL條件:(A = B AND C LIKE%D%)或(A LIKE%B%和C = D)
- 3. {a,b,c,d,e} a,b-> c,a,b-> d和d-> e的最高範式是什麼?
- 4. 對於A,B在C,d的Python
- 5. 合併路徑與Python,從/ A/B/C + C/d到/ A/B/C/d
- 6. VBA生成字符A B C D
- 7. 如何標準化範圍[a,b]到[c,d],其中a映射到d,b映射到c
- 8. 爲什麼流水作業對於(a + b)+(c + d)比對a + b + c + d更好?
- 9. Haskell函數組合 - (a - > b) - >(a - > c) - >(b - > c - > d) - >(a - > d)
- 10. 輸入(a + b)** 2,輸出a * a + a * b + b * a + b * b
- 11. 爲條件執行MCDC(A && B && C)|| D
- 12. (A加入B)加入(C加入d)
- 13. Awestruct:Time.now.strftime( '%A%-d%B%Y')在asciidoc文件
- 14. 從5,2,20,6,6到B,A,D,C,C
- 15. 設計操作(a,b) - >(c,d)
- 16. 使用java將字符串[] str = {「a」,「b」,「c」,「d」,「e」,「f」}映射爲{a = b,c = d,e = f}流
- 17. Python a,b = b,a + b
- 18. PHP變換陣列'a','b','c'到'a/b/c','a/b','a'
- 19. 什麼呢scanf函數( 「%d%d」,&A&B)== 2指
- 20. 爲什麼「{1:'a',True:'b',1.0:'c',1.00:'d'}」評估爲「{1:'d'}」?
- 21. 從{a-b,b-c,c-a}改變爲{(a,b),(b,c),(c,a)}?
- 22. 混合兩個矢量:[a a]和[b b] to [a b a b]
- 23. ORMlite QueryBuilder其中A和B和C和(D或E或F)
- 24. 如何在C#中創建A類,其中A只能由B,C,D繼承?
- 25. 加入2所列出得到(A,d,B,E,C,F),而不是(A,B,C,d,E,F)
- 26. 基於a/b/c/d的輸入返回與* a */* b */* c */* d *匹配的Bash函數?
- 27. 如何以任意精度計算任意大的整數A,B,C和D的(A/B)的(C/D)根?
- 28. 查找函數I(a,b,c,d)積分的四維最小值(a,b,c,d)
- 29. 如何讓mod rewriteconds做'(A和B)或(C和D)'而不是'A和(B或C)和D'?
- 30. Bootstrap中的「Pull center」:A -D- B -E- C列收縮到A-B-C // D-E,如何在D和E之間獲得B?
我想過,但值可能是非常複雜的結構,所以元組永遠是第一要素極爲冗餘(因爲(v1,v2)和(v1,v3)將有v1的兩個副本,如果我沒有引入一個新的結構來存儲指向所有v的指針......)我認爲這使得它相當不雅觀。 – 2010-12-06 16:16:53
也許我會去那個版本,如果另一個是如此困難...我必須重寫哪個成員函數來排序[]運算符中給出的元組,然後將其保存到父代字典中? – 2010-12-06 16:25:58
您必須重寫`__getitem __()`,`__setitem __()`和_ _delitem __()`方法。 http://docs.python.org/reference/datamodel.html#object.__getitem__ – 2010-12-06 16:29:43