我有用于使事情在字典中可哈希标识符

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

我有一个节点类型,它封装为IDENTIFER散列和平等的用途:

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无论你怎么找到的值。

我不相信有使用词典的方式来找回原来的关键k1如果你所有的是K2等于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类或externaly做才能找到一个节点,但在哈希不应该依赖的不是节点的存在。

如果您不能修改(因为你不能修改代码),那么我想你被卡住做ineffecient方式

  

使用添加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归因
不隶属于 StackOverflow
scroll top