簡體   English   中英

在python中,如何從字典中檢索密鑰?

[英]In python, how can you retrieve a key from a dictionary?

我有一個可用的標識符,用於將東西放入字典中:

class identifier():
    def __init__(self, d):
        self.my_dict = d
        self.my_frozenset = frozenset(d.items())
    def __getitem__(self, item):
        return self.my_dict[item]
    def __hash__(self):
        return hash(self.my_frozenset)
    def __eq__(self, rhs):
        return self.my_frozenset == rhs.my_frozenset
    def __ne__(self, rhs):
       return not self == rhs

我有一個節點類型,為了哈希和相等的目的封裝了標識符:

class node:
    def __init__(self, id, value):
        # id is of type identifier
        self.id = id
        self.value = value
        # define other data here...
    def __hash__(self):
        return hash(self.id)
    def __eq__(self, rhs):
        if isinstance(rhs, node):
            return self.id == rhs.id
        ### for the case when rhs is an identifier; this allows dictionary
        ### node lookup of a key without wrapping it in a node
        return self.id == rhs
    def __ne__(self, rhs):
        return not self == rhs

我把一些節點放入字典中:

d = {}
n1 = node(identifier({'name':'Bob'}), value=1)
n2 = node(identifier({'name':'Alex'}), value=2)
n3 = node(identifier({'name':'Alex', 'nationality':'Japanese'}), value=3)
d[n1] = 'Node 1'
d[n2] = 'Node 2'
d[n3] = 'Node 3'

一段時間后,我只有一個標識符:

my_id = identifier({'name':'Alex'})

有沒有辦法有效地查找在此字典中使用此標識符存儲的節點?

請注意,這聽起來有點棘手; 我知道我可以通過使用d[my_id]來檢索相關項'Node 2' ,但我想有效地返回對n2的引用

我知道我可以通過查看d中的每個元素來做到這一點,但我已經嘗試了它並且它太慢了(字典中有數千個項目,我做了很多次)。

我知道內部dict正在使用該標識符的hasheq運算符來存儲節點n2及其相關項'Node 2' 事實上,使用my_id查找'Node 2'實際上需要將n2作為中間步驟進行查找,因此這絕對是可能的。

我用它來將數據存儲在圖表中。 節點有很多額外的數據(我放置value ),這些數據沒有在哈希中使用。 我沒有創建我正在使用的圖形包(networkX),但我可以看到存儲我的節點的字典。 我還可以為節點添加一個額外的字典標識符,但這會很麻煩(我需要包裝圖類並重寫所有添加節點,刪除節點,從列表中添加節點,從列表中刪除節點,添加邊緣等等,以保持該字典為最新的功能。

這是一個難題。 任何幫助將非常感激!

代替

d[n1] = 'Node 1'

使用:

d[n1] = ('Node 1', n1)

然后,無論您如何找到該值,您都可以訪問n1。

如果您擁有的是k2等於k1,我不相信字典有一種方法可以檢索原始密鑰k1。

有兩本詞典。 - 無論何時向主詞典添加鍵/值,還要將它們添加到反向詞典中,但交換鍵/值。

例如:

# When adding a value:
d[n2] = value;
# Must also add to the reverse dictionary:
rev[value] = d

# This means that:
value = d[n2]
# Will be able to efficiently find out the key used with:
key = rev[value]

這是一種在NetworkX中使用自定義節點對象的方法。 如果將對象存儲在“節點屬性”字典中,則可以將其用作反向字典,以通過引用id來獲取對象。 它有點尷尬,但它的工作原理。

import networkx as nx

class Node(object):

    def __init__(self,id,**attr):
        self.id=id
        self.properties={}
        self.properties.update(attr)

    def __hash__(self):
        return self.id

    def __eq__(self,other):
        return self.id==other.id

    def __repr__(self):
        return str(self.id)

    def __str__(self):
        return str(self.id)


G=nx.Graph()
# add two nodes
n1=Node(1,color='red') # the node id must be hashable
n2=Node(2,color='green')
G.add_node(n1,obj=n1)
G.add_node(n2,obj=n2)

# check what we have
print G.nodes() # 1,2
print n1,n1.properties['color'] # 1,red
print n1==n2   # False 
for n in G:
    print n.properties['color']
print Node(1) in G # True
# change color of node 1
n1.properties['color']='blue'
for n in G:
    print n.properties

# use "node attribute" data in NetworkX to retrieve object
n=G.node[Node(1)]['obj']
print type(n) # <class '__main__.Node'>
print n # 1
print n.id # 1
print n.properties # {'color': 'blue'}

你當然可以定義一個使這個更簡單的函數:

   def get_node(G,n):
        return G.node[Node(1)]['obj']

    n=get_node(G,1)
    print n.properties

問題是,沒有保證密鑰實際上是一個節點。 如果你這樣做會怎么樣

d[my_id]=d[my_id] 

除了現在,所有東西仍然可以完美地工作,你的密鑰是標識符,而不是節點。 允許兩個類“相等”這樣是非常危險的。 如果你真的需要找到一個Node的名字,應該在Node類或externaly中完成,但不應該依賴於hash中不存在節點。

如果你不能修改它(因為你不能修改代碼),那么我猜你是堅持做無效的方式

使用my_id查找“節點2”實際上需要查找n2作為中間步驟

事實並非如此 字典是一個哈希表:它將項目的哈希值映射到(一桶)條目。 當你要求d[my_id] ,Python首先得到hash(my_id) ,然后在d查找。 你很困惑,因為你有hash(n1) == hash(id1) ,這是一個非常糟糕的事情。

您要求標識符和節點之間的映射。 如果你想要其中一個,你必須自己創建一個。


標識符在創建時是否都與節點匹配,或者您是否稍后構造它們? 也就是說,您真的要求能夠找到具有標識符identifier({'name':'Alex'})的節點,或者已經創建了該標識符並將其添加到節點中? 如果是后者,您可以執行以下操作:

class Node:
    def __init__(self, id, value):
        id.parent = self
        ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM