我在python中做这个交换机的事情,我需要跟踪谁在跟谁说话,所以如果Alice - > Bob,那么这意味着Bob - > Alice。双向/反向映射
是的,我可以填充两个哈希映射,但我想知道是否有人有一个想法做一个。
或者建议另一个数据结构。
没有多个对话。假设这是针对客户服务呼叫中心的,所以当Alice拨入交换台时,她只会和Bob通话。他的答复也仅限于她。
我在python中做这个交换机的事情,我需要跟踪谁在跟谁说话,所以如果Alice - > Bob,那么这意味着Bob - > Alice。双向/反向映射
是的,我可以填充两个哈希映射,但我想知道是否有人有一个想法做一个。
或者建议另一个数据结构。
没有多个对话。假设这是针对客户服务呼叫中心的,所以当Alice拨入交换台时,她只会和Bob通话。他的答复也仅限于她。
您可以通过继承dict
并添加所需的逻辑来创建自己的字典类型。这里有一个简单的例子:
class TwoWayDict(dict):
def __setitem__(self, key, value):
# Remove any previous connections with these values
if key in self:
del self[key]
if value in self:
del self[value]
dict.__setitem__(self, key, value)
dict.__setitem__(self, value, key)
def __delitem__(self, key):
dict.__delitem__(self, self[key])
dict.__delitem__(self, key)
def __len__(self):
"""Returns the number of connections"""
return dict.__len__(self) // 2
它的工作原理是这样:
>>> d = TwoWayDict()
>>> d['foo'] = 'bar'
>>> d['foo']
'bar'
>>> d['bar']
'foo'
>>> len(d)
1
>>> del d['foo']
>>> d['bar']
Traceback (most recent call last):
File "<stdin>", line 7, in <module>
KeyError: 'bar'
我敢肯定,我没有涵盖所有的情况,但应该让你开始。
@SudhirJonathan:你可以进一步了解这个想法 - 例如,添加一个'.add'方法,以便你可以做像d.add('Bob','Alice')这样的事情而不是使用语法我展示出。我还会包含一些错误处理。但你有基本的想法。:) – 2012-11-07 22:46:58
我想这属于那些补充,但它会有助于删除旧的密钥对,当设置新的('d ['foo'] ='baz''需要另外删除'bar'键) 。 – beardc 2013-01-29 19:10:25
请注意,只有当键和值不会重合时,这才起作用 – 2013-05-28 13:39:17
不,如果不创建两个字典,实在没有办法做到这一点。如何用一本词典实现这一点,同时继续提供可比较的性能?
你最好创建一个封装两个字典并展示你想要的功能的自定义类型。
假设您可以节省内存,两个哈希映射实际上可能是性能最快的解决方案。我会将这些包装在一个类中 - 程序员的负担是确保两个哈希映射正确同步。
+1,这就是[bidict](http://pypi.python.org/pypi/bidict/0.1.1)基本上所做的,加上用于通过使用'mydict [:value]'获得'key '(以一些性能为代价) – 2013-05-29 07:18:40
在你的特殊情况下,你可以同时存储在一个字典:
relation = {}
relation['Alice'] = 'Bob'
relation['Bob'] = 'Alice'
因为你所描述的对称关系。 A -> B => B -> A
嗯......是的,我喜欢这个最好的。正试图避免做两件作品,但这是迄今为止最好的想法。 – 2009-09-21 20:32:37
仍然认为双向映射应该是可能的: -/ – 2009-09-21 20:37:34
如果它必须是有效的,那么在封面下,你需要在一些索引数据结构中索引这两个键 - 无论这是一个散列,一个排序列表,一个二进制树,树状结构,充满sistrings的后缀数组,或更奇特的东西。在Python中执行该操作的简单方法是使用散列。 – 2009-09-22 19:32:06
你有两个单独的问题。
您有一个“对话”对象。它指的是两个人。由于一个人可以有多个对话,你有一个多对多的关系。
您有从人员到对话列表的地图。转换将有一对人员。
做这样的事情
from collections import defaultdict
switchboard= defaultdict(list)
x = Conversation("Alice", "Bob")
y = Conversation("Alice", "Charlie")
for c in (x, y):
switchboard[c.p1].append(c)
switchboard[c.p2].append(c)
的kjbuckets C扩展模块提供了一个“图”的数据结构,我相信给你你想要的东西。
对不起,我没有提到它,但它的应用程序引擎...所以没有C扩展。 – 2009-09-22 05:42:55
您可以使用DoubleDict
,如Python Cookbook上的recipe 578224所示。
另一种可能的解决方案是实现dict
的子类,该子类包含原始字典并跟踪它的反转版本。如果键和值重叠,保持两个独立的字母可能很有用。
class TwoWayDict(dict):
def __init__(self, my_dict):
dict.__init__(self, my_dict)
self.rev_dict = {v : k for k,v in my_dict.iteritems()}
def __setitem__(self, key, value):
dict.__setitem__(self, key, value)
self.rev_dict.__setitem__(value, key)
def pop(self, key):
self.rev_dict.pop(self[key])
dict.pop(self, key)
# The above is just an idea other methods
# should also be overridden.
例子:
>>> d = {'a' : 1, 'b' : 2} # suppose we need to use d and its reversed version
>>> twd = TwoWayDict(d) # create a two-way dict
>>> twd
{'a': 1, 'b': 2}
>>> twd.rev_dict
{1: 'a', 2: 'b'}
>>> twd['a']
1
>>> twd.rev_dict[2]
'b'
>>> twd['c'] = 3 # we add to twd and reversed version also changes
>>> twd
{'a': 1, 'c': 3, 'b': 2}
>>> twd.rev_dict
{1: 'a', 2: 'b', 3: 'c'}
>>> twd.pop('a') # we pop elements from twd and reversed version changes
>>> twd
{'c': 3, 'b': 2}
>>> twd.rev_dict
{2: 'b', 3: 'c'}
有PyPI上集合扩展库:https://pypi.python.org/pypi/collections-extended/0.6.0
使用双射类是那么容易,因为:
RESPONSE_TYPES = bijection({
0x03 : 'module_info',
0x09 : 'network_status_response',
0x10 : 'trust_center_device_update'
})
>>> RESPONSE_TYPES[0x03]
'module_info'
>>> RESPONSE_TYPES.inverse['network_status_response']
0x09
我知道这是一个老问题,但我想提出另一个很好的解决方案,即python包bidict。这是非常直接的使用:
from bidict import bidict
map = bidict(Bob = "Alice")
print(map["Bob"])
print(map.inv["Alice"])
请注意,你正在描述一个双射图。 – 2009-09-21 19:47:01
如果爱丽丝和鲍勃谈话,我认为她不能和查尔斯谈话;鲍勃也无法与其他人交谈?此外,您可以在任何时间多少人以及多少次对话? – 2009-09-21 20:15:09
不......在我的交换机上。爱丽丝发给我的任何消息都必须发给鲍勃。它只是我会路由成千上万的同时对话。但每个人一次只能与另一个人谈话。 – 2009-09-21 20:31:25