【问题标题】:Is there a better way to store a twoway dictionary than storing its inverse separate? [duplicate]有没有比单独存储逆字典更好的方法来存储双向字典? [复制]
【发布时间】:2013-05-23 12:16:30
【问题描述】:

给定一个一对一的字典 (=bijection) 生成 à la

for key, value in someGenerator:
     myDict[key] = value

可以通过添加轻松创建逆向查找字典

    invDict[value] = key

for 循环。但这是一种 Pythonic 方式吗?我应该写一个class Bijection(dict) 来管理这个倒排字典并提供第二个查找功能吗?或者这样的结构(或类似结构)是否已经存在?

【问题讨论】:

  • 这个bidict怎么样
  • 从表面上看,bidict 只是用正向和反向映射包装了两个独立的 Python 字典,所以它并不比自己做同样的事情更有效率。事实上,如果您要进行大量键查找,由于函数调用开销,它会慢得多。
  • 这几乎不是一个答案,我也没有实际使用它来个人推荐它的经验。不过需要注意的是,如果我没记错的话,关于该库的 API 在使用切片表示法时是否是 Pythonic 存在一些相当激烈的争论。但是,情人眼中的美丽等等。
  • @TobiasKienzler 确实如此。 try/except 块也会减慢速度。在实践中,我发现 return d[k] if k in d else something_elsetry: return d[k]\n except KeyError: return something_elsereturn d.get(k, something_else) 快得多,即两个键查找比允许 Python 生成异常和/或调用实例方法更快。就个人而言,我认为它没有提供足够的额外功能(与仅使用两个 dict 相比)来保证其性能问题,但如果这不是问题,那么它至少具有易于使用的优点。
  • @TobiasKienzler 好吧,我最近不得不优化一个相当复杂的递归函数,它被调用了 150,000 次,所以我花了很长时间用 cProfile 分析不同的方法,并设法节省了很多使用 d[k] if k in d 方法的 CPU 时间。后来我将其更改为使用 d = collections.defaultdict(lambda: None); v = d[k]; return something_else if v is None else v 更好,因为它只需要一个键查找,键未命中只发生一次,并且 defaultdict 是用 C 实现的。你对 namedbidict 是正确的 - 我读错了这是第一次。

标签: python dictionary


【解决方案1】:

如果您想要 O(log(n)) 时间来访问值,您将需要映射的表示和逆映射的表示。

否则,您可以做的最好的事情是在一个方向上为 O(log(n)),在另一个方向上为 O(n)。

编辑:不是 O(log(n)),感谢 Claudiu,但您仍然需要两个数据结构来实现快速访问时间。这将或多或少与 dict 和 inverse dict 相同的空间。

【讨论】:

  • dicts 没有 O(log(n)) 查找,它们已摊销 O(1) 查找...
  • 是的,在我发帖之前应该查一下 :)
【解决方案2】:

我过去所做的是创建了一个 reversedict 函数,该函数将接受一个 dict 并返回相反的映射,如果我知道它是一对一的,则要么值到键(在看到两次相同的值),或者键列表的值(如果不是)。这样,每次我想要反向查找时都不必同时构造两个字典,我可以像平常一样创建我的字典,然后在最后调用通用 reversedict 函数。

但是,Jon 在 cmets 中提到的 bidict 解决方案似乎可能是更好的解决方案。 (我的reversedict 函数似乎是他的bidict 的~ 运算符)。

【讨论】:

  • bidict 非常适合我的目的 - 它基本上将逆字典存储在里面,但通过使用切片运算符改进了访问
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-23
  • 1970-01-01
  • 2017-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-24
相关资源
最近更新 更多