我在python中做这个总机,需要跟踪谁在和谁说话,所以如果Alice-> Bob,那意味着Bob-> Alice。
是的,我可以填充两个哈希图,但是我想知道是否有人想使用一个哈希图。
或建议其他数据结构。
没有多个对话。假设这是一个客户服务呼叫中心,所以当爱丽丝拨入总机时,她只会和鲍勃交谈。他的答复也只发给她。
我在python中做这个总机,需要跟踪谁在和谁说话,所以如果Alice-> Bob,那意味着Bob-> Alice。
是的,我可以填充两个哈希图,但是我想知道是否有人想使用一个哈希图。
或建议其他数据结构。
没有多个对话。假设这是一个客户服务呼叫中心,所以当爱丽丝拨入总机时,她只会和鲍勃交谈。他的答复也只发给她。
Answers:
您可以通过子类化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'
我确定我没有涵盖所有情况,但这应该可以帮助您入门。
.add
方法,以便您可以执行类似的操作,d.add('Bob', 'Alice')
而不使用我显示的语法。我还将包括一些错误处理。但是您了解了基本思想。:)
d['foo'] = 'baz'
需要另外删除bar
密钥)。
dict
在这里会产生一些误导性的行为,因为如果您创建具有一些初始内容的对象,结构就会被破坏。__init__
需要被覆盖以使建筑d = TwoWayDict({'foo' : 'bar'})
能够正常工作。
pip install bidict
。网址:pypi.python.org/pypi/bidict
在特殊情况下,您可以将两者存储在一个字典中:
relation = {}
relation['Alice'] = 'Bob'
relation['Bob'] = 'Alice'
由于您要描述的是对称关系。 A -> B => B -> A
我只是用第二个哈希填充
reverse_map = dict((reversed(item) for item in forward_map.items()))
reverse_map = dict(reversed(item) for item in forward_map.items())
my_dict.update(dict(reversed(item) for item in my_dict.items()))
Unexpected type(s): (Generator[Iterator[Union[str, Any]], Any, None]) Possible types: (Mapping) (Iterable[Tuple[Any, Any]])
。任何想法如何摆脱警告?
您有两个单独的问题。
您有一个“对话”对象。它指的是两个人。由于一个人可以进行多个对话,因此您具有多对多关系。
您有一个从人到会话列表的映射。一个转换将有一对人。
做这样的事情
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 )
另一种可能的解决方案是实现的子类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上有collections-extended库:https ://pypi.python.org/pypi/collections-extended/0.6.0
使用bijection类非常简单:
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
我喜欢其中一项评论中关于二分法的建议。
pip install bidict
# This normalization method should save hugely as aDaD ~ yXyX have the same form of smallest grammar.
# To get back to your grammar's alphabet use trans
def normalize_string(s, nv=None):
if nv is None:
nv = ord('a')
trans = bidict()
r = ''
for c in s:
if c not in trans.inverse:
a = chr(nv)
nv += 1
trans[a] = c
else:
a = trans.inverse[c]
r += a
return r, trans
def translate_string(s, trans):
res = ''
for c in s:
res += trans[c]
return res
if __name__ == "__main__":
s = "bnhnbiodfjos"
n, tr = normalize_string(s)
print(n)
print(tr)
print(translate_string(n, tr))
由于没有太多相关文档。但是我可以正常使用所有需要的功能。
abcbadefghei
bidict({'a': 'b', 'b': 'n', 'c': 'h', 'd': 'i', 'e': 'o', 'f': 'd', 'g': 'f', 'h': 'j', 'i': 's'})
bnhnbiodfjos
这是通过扩展pythons dict
类的另一种双向字典实现,以防您不喜欢其他任何字典:
class DoubleD(dict):
""" Access and delete dictionary elements by key or value. """
def __getitem__(self, key):
if key not in self:
inv_dict = {v:k for k,v in self.items()}
return inv_dict[key]
return dict.__getitem__(self, key)
def __delitem__(self, key):
if key not in self:
inv_dict = {v:k for k,v in self.items()}
dict.__delitem__(self, inv_dict[key])
else:
dict.__delitem__(self, key)
除了构造以外,将其用作普通的python字典:
dd = DoubleD()
dd['foo'] = 'bar'