2014-01-31 38 views
1

我有一個應用程序,我有一組命名節點。對於每對節點,我想存儲它們的連接值。節點會隨着時間的推移而來,所以我無法初始化一個「數組」開始。名稱不是順序整數,而是任意對象標識或字符串名稱。從一對或名稱映射到Python中的值

我需要能夠做到:

lookup(name1, name2) -> value 

而且還

set(name1, name2, value) 

而且,當一個新的節點加入,要做到:

set(newname, [all other nodes], default_value) 

的假設是,對於每一對,方向並不重要。即,(name1,name2)應該具有與(name2,name1)相同的值。

這方面最明顯的Python實現似乎是一個兩級詞典:

{ name1 : { name2: value, name3:value}, name2: {name1:value, name3:value}, ... etc. } 

那是最好的方式做到這一點?

UPDATE

使用具有對作爲鍵的字典的建議可能是Python的內部更好。但是,我還發現有一個側面限制,可以導出和導入數據集作爲列表清單(以便支持Simics模擬器內部的狀態序列化) - 並且爲此,兩級映射是非常自然。但我猜這對夫婦也會在那裏工作。實際上很難說什麼更好。

+0

這個數據結構看起來很像一個圖表,雖然圖表可能對你的應用程序來說是過分的。看看networkx或igraph ... –

+0

這是一個圖表,但它是一個完全連接的圖表,因此一般圖形可能是矯枉過正的。 – jakobengblom2

回答

2

你可以使用frozenset()鍵:

{frozenset([name1, name2]): value, frozenset([name2, name3]): other_value} 

的優點是frozenset()對象可以作爲鑰匙,節點的順序並不重要; frozenset([name1, name2])等於frozenset([name2, name1])

要獲得所有節點的列表,你不得不使用:

all_nodes = reduce(frozenset.union, yourdict.keys()) 

如果是這樣的Python 2,使用yourdict.iterkeys()代替。從這裏你就可以生產所有可能的組合來設置一個默認值:

from itertools import permutations: 

for name1, name2 in permutations(all_nodes, r=2): 
    key = frozenset([name1, name2]) 
    if key not in yourdict: 
     yourdict[key] = default_value 

另外,如果你包裹在一個類(可能是個好主意)的整體結構,你可以添加跟蹤節點的額外指標也可以在更新實例時使該索引保持最新。

1

或者您可以使用字典,元組作爲鍵

{(name1, name2) : value, (name1, name3) : value, (name2, name1) : value, ...} 

,而不是

{name1 : {name2 : value, name3 : value}, name2 : {name1 : value, ...}, ... etc.} 

然後操作將是如下所示:

values = {(name1, name2) : value, (name1, name3) : value, (name2, name1) : value, ...} 

def lookup(name1, name2): 
    return values[name1, name2] 

def set(name1, name2, value): 
    values[name1, name2] = value 
    values[name2, name1] = value # for symmetry 

附:不浪費內存默認連接性值可以修改查找類似如下:

def lookup(name1, name2): 
    return values.get((name1, name2), default_value) 

但在這種情況下,你會得到default_value不中一組節點。

+2

但是這不會處理'(name2,name1)'與'(name1,name2)'相同。 –

+0

@MartijnPieters,如果我們只使用定義的'lookup'和'set'操作,那麼從外部的角度來看就沒有什麼區別。當然fronzensets仍然可以用來減半使用的內存。 – citxx

+0

這很可能與我所做的一樣好;但最終結果在語法上非常相似。我得到foo [name1] [name2]而不是foo [name1,name2]。 – jakobengblom2

相關問題