【问题标题】:How do you retrieve items from a dictionary in the order that they're inserted?如何按照插入的顺序从字典中检索项目?
【发布时间】:2008-09-13 20:38:05
【问题描述】:

是否可以按照插入的顺序从 Python 字典中检索项目?

【问题讨论】:

  • 这个问题(和过时的接受答案)仍然是谷歌搜索“python dict items by insert order”的第一结果。如果您正在阅读本文,请投票支持 Brian 2018 年的回答。

标签: python dictionary


【解决方案1】:

如果您使用 CPython 3.6+(或 Python 3.7+ 用于任何其他 Python 实现),标准 Python dict 默认会执行此操作。

在旧版本的 Python 上,您可以使用 collections.OrderedDict

【讨论】:

    【解决方案2】:

    使用 OrderedDict(),从 2.7 版开始提供

    只是好奇:

    from collections import OrderedDict
    a = {}
    b = OrderedDict()
    c = OrderedDict()
    
    a['key1'] = 'value1'
    a['key2'] = 'value2'
    
    b['key1'] = 'value1'
    b['key2'] = 'value2'
    
    c['key2'] = 'value2'
    c['key1'] = 'value1'
    
    print a == b  # True
    print a == c  # True
    print b == c  # False
    

    【讨论】:

      【解决方案3】:

      从 Python 3.7 开始,标准 dict 保留插入顺序。来自docs

      在 3.7 版更改:保证字典顺序为插入顺序。这种行为是 CPython 3.6 的实现细节。

      因此,您应该能够正常遍历字典或使用popitem()

      【讨论】:

      • 让我们对这个答案进行投票。另外从文档中,第 5.5 节字典:“在字典上执行 list(d) 会返回字典中使用的所有键的列表,按插入顺序排列(如果要对其进行排序,只需使用 sorted(d) 代替)。”
      【解决方案4】:

      其他答案都是正确的;这是不可能的,但你可以自己写。但是,如果您不确定如何实际实现这样的东西,这里有一个完整且有效的实现,它继承了我刚刚编写和测试的 dict 的子类。 (请注意,传递给构造函数的值的顺序是未定义的,但会在稍后传递的值之前出现,并且您总是可以不允许使用值初始化有序 dicts。)

      class ordered_dict(dict):
          def __init__(self, *args, **kwargs):
              dict.__init__(self, *args, **kwargs)
              self._order = self.keys()
      
          def __setitem__(self, key, value):
              dict.__setitem__(self, key, value)
              if key in self._order:
                  self._order.remove(key)
              self._order.append(key)
      
          def __delitem__(self, key):
              dict.__delitem__(self, key)
              self._order.remove(key)
      
          def order(self):
              return self._order[:]
      
          def ordered_items(self):
              return [(key,self[key]) for key in self._order]
      
      
      od = ordered_dict()
      od["hello"] = "world"
      od["goodbye"] = "cruel world"
      print od.order()            # prints ['hello', 'goodbye']
      
      del od["hello"]
      od["monty"] = "python"
      print od.order()            # prints ['goodbye', 'monty']
      
      od["hello"] = "kitty"
      print od.order()            # prints ['goodbye', 'monty', 'hello']
      
      print od.ordered_items()
      # prints [('goodbye','cruel world'), ('monty','python'), ('hello','kitty')]
      

      【讨论】:

      • order_dict( ('key_a','value_a'), ('key_b','value_b') ) 的顺序是否正确?看起来 _order 将在 init 中设置为 self.keys(),它是按哈希排序排序的,而不是它输入的顺序?只是好奇。
      • 你是对的,这就是为什么我说,“传递给构造函数的值的顺序是未定义的,但会在稍后传递的值之前”。可以正确订购它们,但我不确定这是否是一种理想的行为,因为可以说这些对象是同时插入的。
      【解决方案5】:

      你不能用基本的 dict 类来做到这一点——它是按哈希排序的。您可以构建自己的字典,它实际上是键、值对或类似的列表,它们将被排序。

      【讨论】:

      • 您的字典实现可以改为使用标准字典和列表 - 字典存储键->值关联,列表按插入顺序存储键。
      【解决方案6】:

      或者,只需将 key 设为元组,将 time.now() 作为元组中的第一个字段。

      然后您可以使用 dictname.keys() 检索键,排序,瞧!

      格里

      【讨论】:

      • 这使得在不知道您插入它们的确切时间的情况下查找字典中的条目是不可能的。它并不比键值对列表更好。
      【解决方案7】:

      我以前使用过 StableDict 并取得了不错的成功。

      http://pypi.python.org/pypi/StableDict/0.2

      【讨论】:

        【解决方案8】:

        或者使用PEP-372 描述的here 的任何实现,例如pythonutils 中的odict module

        我成功使用了 pocoo.org 实现,就像替换你的一样简单

        my_dict={}
        my_dict["foo"]="bar"
        

        my_dict=odict.odict()
        my_dict["foo"]="bar"
        

        只需要this file

        【讨论】:

          【解决方案9】:

          除非您将密钥存储在单独的列表中以供以后参考,否则这是不可能的。

          【讨论】:

            【解决方案10】:

            如果您不需要 dict 功能,而只需要按照插入的顺序返回元组,队列不是更好吗?

            【讨论】:

              【解决方案11】:

              您可以使用代表输入顺序的键插入值,然后在项目上调用sorted()

              >>> obj = {}
              >>> obj[1] = 'Bob'
              >>> obj[2] = 'Sally'
              >>> obj[3] = 'Joe'
              >>> for k, v in sorted(obj.items()):
              ...     print v
              ... 
              Bob
              Sally
              Joe
              >>> 
              

              【讨论】:

              • 如果我们不需要密钥用于其他目的,我们将使用一个列表。这无济于事,列表做得更好。
              • @user2357112,然而,这表达了另一种执行OP要求的方法。 OP 没有询问如何按插入顺序打印项目,OP 说如何在dict 中打印项目。大不同。
              • 不过,您已将 dict 的格式更改为使其无法用于原始目的。如果 dict 最初将姓名与电话号码相关联,则您获得了一致的迭代顺序,但您不知道 Bob 的电话号码是什么。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2013-11-01
              • 2019-03-29
              • 1970-01-01
              • 2012-08-23
              • 1970-01-01
              • 2018-05-31
              • 2016-12-01
              相关资源
              最近更新 更多