双向/反向地图

Sud*_*han 88 python

我在python中做这个交换机的事情,我需要跟踪谁和谁说话,所以如果Alice - > Bob,那么暗示Bob--> Alice.

是的,我可以填充两个哈希映射,但我想知道是否有人有想法用一个哈希映射.

或建议另一种数据结构.

没有多个对话.假设这是一个客户服务呼叫中心,所以当Alice拨入交换机时,她只会和Bob通话.他的回复也只发给她.

Sas*_*gov 83

您可以通过子类化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
Run Code Online (Sandbox Code Playgroud)

它的工作原理如下:

>>> 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'
Run Code Online (Sandbox Code Playgroud)

我确定我没有涵盖所有情况,但这应该让你开始.

  • 请注意,这仅在键和值不重合时才有效 (32认同)
  • 只是想提一下这里有一个库:`pip install bidict`.网址:https://pypi.python.org/pypi/bidict/ (16认同)
  • 另外值得一提的是:子类化`dict`会在这里产生一些误导行为,因为如果你用一些初始内容创建对象,结构将被破坏.需要覆盖`__init__`以允许像`d = TwoWayDict({'foo':'bar'})`这样的构造才能正常工作. (4认同)
  • @SudhirJonathan:您可以更进一步了解这个想法 - 例如,添加一个`.add`方法,以便您可以执行诸如`d.add('Bob','Alice')之类的操作,而不是使用语法I显示.我还会包含一些错误处理.但是你得到了基本的想法.:) (2认同)

Nad*_*mli 43

在您的特殊情况下,您可以将它们存储在一个字典中:

relation = {}
relation['Alice'] = 'Bob'
relation['Bob'] = 'Alice'
Run Code Online (Sandbox Code Playgroud)

因为你所描述的是对称关系. A -> B => B -> A

  • 嗯......是的,我最喜欢这个.试图避免两个条目,但这是迄今为止最好的主意. (3认同)
  • 仍然认为应该可以使用双向地图:-/ (2认同)

Ian*_*and 22

我会填充第二个哈希值

reverse_map = dict((reversed(item) for item in forward_map.items()))
Run Code Online (Sandbox Code Playgroud)

  • 在那里有一些额外的括号:`reverse_map = dict(reverse(map)for forward_map.items()中的项目) (5认同)

Nea*_*roo 17

我知道这是一个较老的问题,但我想提一下这个问题的另一个很好的解决方案,即python包bidict.它非常直接使用:

from bidict import bidict
map = bidict(Bob = "Alice")
print(map["Bob"])
print(map.inv["Alice"])
Run Code Online (Sandbox Code Playgroud)

  • `map` 隐藏了 python 内置关键字 'map' (5认同)

小智 9

一种不太冗长的方法,仍然使用反向:

dict(map(reversed, my_dict.items()))
Run Code Online (Sandbox Code Playgroud)


Tri*_*ych 8

假设您可以节省内存,两个哈希映射实际上可能是性能最快的解决方案.我会将它们包装在一个类中 - 程序员的负担是确保两个哈希映射正确同步.

  • +1,这就是 [bidict](http://pypi.python.org/pypi/bidict/0.1.1) 基本上所做的,加上通过使用`mydict[:value]` 获取`key 来访问逆映射的糖`(以牺牲一些性能为代价) (2认同)

And*_*are 5

不,如果不创建两个字典,真的没有办法做到这一点。如何在继续提供可比性能的同时仅用一本字典来实现这一点?

您最好创建一个自定义类型来封装两个字典并公开您想要的功能。


S.L*_*ott 5

你有两个不同的问题.

  1. 你有一个"对话"对象.它指的是两个人.由于Person可以进行多次对话,因此您具有多对多关系.

  2. 您有一个从人员到对话列表的地图.转换将有一对人.

做这样的事情

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 )
Run Code Online (Sandbox Code Playgroud)