【问题标题】:Python support sorted dictionary -- similar to C++ map?Python 支持排序字典——类似于 C++ 映射?
【发布时间】:2016-05-21 15:23:00
【问题描述】:

我使用的是 Python 2.7.x。我有一本字典(我的意思是{}),键是int,值是字符串。我想检索具有最小整数值的键。在 C++ 中,我认为我们可以使用 map,它对键进行排序。在 Python 中,不确定我们是否可以利用类似的东西?如果我的理解是正确的,Python 字典(我的意思是{})不是按键排序的。

提前致谢, 林

【问题讨论】:

  • 如果可以提前排序,也许docs.python.org/2/library/…
  • @LinMa:不,你不需要dict,一个RB树就足以完成关联容器的事情(键=>值映射是O(log n))和保持排序的东西(std::map 通常实现为 RB 树)。但是请注意,dict 在一般情况下具有 O(1) 查找(如 C++ 中的 std::unordered_map),并且在解释器中直接用 C 语言编写,因此,根据实现,RB 树可能要慢得多(尤其是如果它是用纯 Python 实现的)。
  • @LinMa:任何需要查找的东西。
  • @LinMa:they claim SortedDict is faster 不是基于树的实现,但请随意对两者进行基准测试,看看哪种方法最适合您。从使用的角度来看,它们应该基本相同。

标签: python c++ dictionary


【解决方案1】:

更新

OP 表示在查找字典中的最小键时需要 O(1) 性能。试试sortedcontainers 模块。它提供了一个SortedDict 类:

>>> from sortedcontainers import SortedDict
>>> d = SortedDict({100: 'a', 27: 'b', 1234: 'c'})
>>> d.keys()
SortedSet([27, 100, 1234], key=None, load=1000)
>>> d.keys()[0]
27
>>> d[d.keys()[0]]
'b'

对于 Python 内置字典,您可以使用 min(d) 查找最低键:

>>> d = {100: 'a', 27: 'b', 1234: 'c'}
>>> print(d)
{1234: 'c', 27: 'b', 100: 'a'}
>>> print(min(d))
27
>>> print(d[min(d)])
b

【讨论】:

  • 这可能比根据我的解决方案使用有序字典更容易。
  • 或者,不是对所有键进行排序,而是取最小值:min(d.keys())
  • @jgfооt:谢谢!其实这就是我最初想做的,但是在写答案的时候忘记了。
  • 或者,如果您希望它作为键值对:min(d.iteritems())
  • 应该提到的是,min()map.first() 的等效 C++ 代码中将是 O(n) 而不是 O(1)。根据需要,这可能会或可能不会重要。
【解决方案2】:

Python中有二叉树的实现:

https://pypi.python.org/pypi/bintrees/2.0.2

您也可以使用blist.sorteddict

您还可以使用内置的bisect 模块来维护一个有序的元组列表。

如果您只关心找到最小值并且您实际上并不关心维护排序,您可以使用内置的heapq 模块来维护一个最小堆数据结构,让您可以持续访问最小的元素。

【讨论】:

    【解决方案3】:

    在 Python 中,字典在内部由哈希表表示,因此您无法以原生方式按排序顺序取回键。您可以使用sorted(d.keys()) 按排序顺序返回键列表。如果您对键进行预排序,您也可以使用collections.OrderedDict。如果您事先不知道键的顺序,并且需要在插入值时保持键的排序顺序,您可以查看 this library 的 SortedDict 类型。

    【讨论】:

    • 你可能应该提到它是collections.OrderedDict
    • 感谢 Kurt,如果我需要动态添加/删除元素(无法提前决定),我可以使用 OrderedDict 吗?谢谢。
    • @LinMa collections.OrderedDict 仅维护插入顺序中的项目而不是排序顺序。这就是为什么您必须提前知道密钥顺序的原因。该链接处的库保持排序顺序。
    • 感谢库尔特,让我确认我的理解是正确的,因为您提供了多个很好的参考。 :) 对于您认为解决我的问题的库,它是 SortedDict,而不是 OrderedDict,对吗?谢谢。
    【解决方案4】:

    根据@mhawke 的回答,您可以简单地这样做:

    d = {1 : "a", 2 : "b", 3 : "c" }
    print d[min(d.keys())] # => 'a'
    

    【讨论】:

    • 谢谢大家,我正在做与你现在做的相同的实现,但担心的是 min 将是 O(n) 而不是 O(1)。感谢您的建议。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2017-10-26
    • 1970-01-01
    • 2015-02-05
    • 1970-01-01
    • 2020-03-15
    • 2015-10-17
    • 1970-01-01
    • 2021-11-15
    相关资源
    最近更新 更多