按SORTED顺序在字典中添加键

时间:2013-03-19 05:07:16

标签: python dictionary key sorted

假设我有一本字典

{1:5, 2:5, 4:5}

是否存在数据结构,如果我添加键值对3:5,是否将其输入字典中以使键按顺序排列?即

{1:5, 2:5, 3:5, 4:5}

我知道collections.OrderedDict(),但这只会按照添加顺序保存密钥(这对我来说还不够)。

我不想使用普通字典dic = {},然后必须使用sorted(dic)[0]来获取最小的密钥。我宁愿拥有sorted_dict[0]类型的功能 这样做的原因是,如果我使用普通字典,我将不得不多次调用排序,因为我不断在我的字典中添加对。

编辑:我应该提到,它不仅是我关心的最小和最大的键,我还需要定期打印这本词典......

3 个答案:

答案 0 :(得分:5)

如果您打算连续添加和删除字典中的键,您真的需要使用适当的数据结构来解决问题 - 而不是哈希表(或哈希表加列表,就像{{1}一样) } -type recipes),但是一个平衡的树(或等同的,如跳过列表)。

如果你环顾一下PyPI,你会发现很多选择。我的建议是blist。尽管它的数据结构可能不像其他一些数据结构那样最优(因为B +树比二叉树更广泛),但对于几乎所有遇到的用例来说,它可能已经足够好了。它拥有完整且经过良好测试的界面,包括经过良好测试的性能保证。其他严肃的项目也使用了它。

如果您正在处理树性能真正关键的罕见情况之一,您应该查看各种红黑树,splay树,skiplist等实现。我之前使用过bintrees,它有一个很好的界面(例如,你可以通过索引访问键和值,甚至切片树,以及像SortedOrderedDict那样对待它,以及作者已经思考并避免了所有潜在的歧义),但我没有认真对其进行性能测试。

或者,如果您的键和值确实都是小整数,您可能需要考虑使用Cython在Pythonic界面中包装C ++ dict。 (在C ++ map<int, int>之上提供完整的接口是不可能的,但是你通常不需要它。)或者,修改其中一个实现,如{{ 1}}来存储和比较map而不是bintrees.FastRBTree

另一方面,如果您只想一次创建字典然后使用它,那么答案会更简单。对它进行排序,并将其粘贴在long中。那么你不需要stdlib以外的任何东西。

PyObject*

根据对其他答案的评论,您说“我没有权限安装新模块......”

首先,确保这是真的。您可能 do 有权在用户site-packages目录中安装模块。或者,如果安装了OrderedDict和/或您使用内置sorted_dict = collections.OrderedDict(sorted(d.iteritems())) 的3.3,甚至更好,您可能有权创建一个venv并在其中安装模块。

但如果是这样,您需要做的是将virtualenv / venv /中的文件复制到您的项目中。

您可能遇到的问题是大多数这些软件包都包含C扩展模块,这意味着您必须能够构建它们(好吧,blist它们)。如果您的系统没有安装Python dev文件和编译器工具链,则无法执行此操作。在这种情况下,您正在寻找最好的纯Python解决方案。 bintrees附带一个纯Python实现,与普通的C扩展实现相同,但速度较慢。当然,它仍然是O(log N),只是常数因子要高很多。如果N足够大,它仍然是一个巨大的胜利;如果没有,可能不是。

如果这听起来合理,但您需要帮助设置每用户的网站包或虚拟环境,或者将模块复制到您的项目中,或者在现场构建扩展等等,应该搜索现有问题,如果你找不到问题,可以问一个新问题(如果没有其他原因,因为安装问题的专家不一定是数据结构的专家,甚至可能不是正在读这个问题)。

答案 1 :(得分:3)

尝试此食谱 - http://code.activestate.com/recipes/576998-sorted-dictionary/

它使用stdlib bisect模块对键进行排序。

答案 2 :(得分:1)

晚了一年多,但我想建议sortedcontainers模块。像blist和bintrees一样,它提供了SortedDict数据类型,可以按排序顺序维护密钥。与那些模块不同,它是用纯Python编写的,实际上更快。 SortedDict还支持索引。查找最小值/最大值实际上发生在O(1)时间内。

由于它是纯Python,因此使用pip进行安装应该是轻而易举的事情:

pip install sortedcontainers

然后你可以简单地导入SortedDict

In [1]: from sortedcontainers import SortedDict

In [2]: d = SortedDict({1:5, 2:5, 4:5})

In [3]: d
Out[3]: SortedDict({1: 5, 2: 5, 4: 5})

In [4]: d[3] = 5

In [5]: d
Out[5]: SortedDict({1: 5, 2: 5, 3: 5, 4: 5})

如果您在使用pip安装内容时遇到困难,或者无法复制需要编译的文件,那么您只需将sortedlist.py和sorteddict.py文件从软件仓库中取出即可。所有代码都是open source on github

sortedcontainers模块还提供了一个performance comparison,其中最流行的建议是相互对照的。