【问题标题】:How can I sort a dictionary by key?如何按键对字典进行排序?
【发布时间】:2012-02-18 13:35:04
【问题描述】:

{2:3, 1:89, 4:5, 3:0}{1:89, 2:3, 3:0, 4:5} 的好方法是什么?
我检查了一些帖子,但它们都使用返回元组的“排序”运算符。

【问题讨论】:

  • @KarlKnechtel - 我的用例是我有一个 CLI 应用程序,它有一个原始菜单,并且菜单选项在字典中作为键。为了用户的理智,我想按字母顺序显示键。
  • @Nayuki,鉴于这是一个 Python 问题,我将字典等同于 dict
  • 请注意,字典现在按插入顺序排序(python 3.6+)。下面的一些答案指出了这一点。
  • @matiasg 请注意,在 Python 3.6 中,保留插入顺序的字典是 CPython 的一个实现细节。在 Python 3.7 中,字典的插入顺序保存正式成为该语言的一部分

标签: python sorting dictionary


【解决方案1】:

标准 Python 字典是无序的(直到 Python 3.7)。即使您对 (key,value) 对进行了排序,也无法以保留顺序的方式将它们存储在 dict 中。

最简单的方法是使用OrderedDict,它会记住插入元素的顺序:

In [1]: import collections

In [2]: d = {2:3, 1:89, 4:5, 3:0}

In [3]: od = collections.OrderedDict(sorted(d.items()))

In [4]: od
Out[4]: OrderedDict([(1, 89), (2, 3), (3, 0), (4, 5)])

不要介意od 的打印方式;它会按预期工作:

In [11]: od[1]
Out[11]: 89

In [12]: od[3]
Out[12]: 0

In [13]: for k, v in od.iteritems(): print k, v
   ....: 
1 89
2 3
3 0
4 5

Python 3

对于 Python 3 用户,需要使用 .items() 而不是 .iteritems()

In [13]: for k, v in od.items(): print(k, v)
   ....: 
1 89
2 3
3 0
4 5

【讨论】:

  • 谢谢,我使用的是 python 2.6.5,OrderedDict 适用于 2.7 及更高版本,因此无法正常工作..
  • @achrysochoou:如果这行得通,那一定是幸运的。正如您被告知的那样,常规字典没有排序的概念,无论您分配的键是排序的还是随机的。
  • 对于python 3.7+:sorted_dict = dict(sorted(unsorted_dict.items()))
  • python 3.7+ 不需要orderedDict,因为它现在默认订购:-)
  • 来自 python 3.7.4 手册:“在字典上执行 list(d) 将返回字典中使用的所有键的列表,按插入顺序”。所以插入顺序是保留下来的,我们可以依赖。
【解决方案2】:

正如其他人所提到的,字典本质上是无序的。但是,如果问题只是以有序方式显示字典,您可以覆盖字典子类中的__str__ 方法,并使用此字典类而不是内置的dict。例如。

class SortedDisplayDict(dict):
   def __str__(self):
       return "{" + ", ".join("%r: %r" % (key, self[key]) for key in sorted(self)) + "}"


>>> d = SortedDisplayDict({2:3, 1:89, 4:5, 3:0})
>>> d
{1: 89, 2: 3, 3: 0, 4: 5}

注意,这不会改变密钥的存储方式、迭代它们时它们返回的顺序等,只是它们在 print 或 python 控制台中的显示方式。

【讨论】:

    【解决方案3】:

    字典本身没有这样的排序项目,如果您想按某种顺序打印它们等,这里有一些示例:

    在 Python 2.4 及更高版本中:

    mydict = {'carl':40,
              'alan':2,
              'bob':1,
              'danny':3}
    
    for key in sorted(mydict):
        print "%s: %s" % (key, mydict[key])
    

    给予:

    alan: 2
    bob: 1
    carl: 40
    danny: 3
    

    (Python 2.4 以下:)

    keylist = mydict.keys()
    keylist.sort()
    for key in keylist:
        print "%s: %s" % (key, mydict[key])
    

    来源:http://www.saltycrane.com/blog/2007/09/how-to-sort-python-dictionary-by-keys/

    【讨论】:

    • 您也可以在 python 2.4+ 中使用 OrderedDict,如 NPE 的回答中所示
    • 如果你使用 items() 你可以像for key, value in sorted(mydict.items())"
    • 字典本身并没有这样的排序项目 -> 不再正确!
    • 怎么回事,能解释一下吗?
    • @James See link.
    【解决方案4】:

    来自Python's collections library documentation

    >>> from collections import OrderedDict
    
    >>> # regular unsorted dictionary
    >>> d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}
    
    >>> # dictionary sorted by key -- OrderedDict(sorted(d.items()) also works
    >>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
    OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
    
    >>> # dictionary sorted by value
    >>> OrderedDict(sorted(d.items(), key=lambda t: t[1]))
    OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])
    
    >>> # dictionary sorted by length of the key string
    >>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
    OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])
    

    【讨论】:

    • 太棒了!伙计们,如果您想反转顺序(升序到降序),那么您只需添加 reverse=True 例如OrderedDict(sorted(d.items(), reverse=True, key=lambda t: t[0]))
    • 在 PyCharm 中,无论我使用什么字典,我总是收到这个警告:Unexpected type(s): (List[str]) Possible types: (Mapping) (Iterable[Tuple[Any, Any]])
    【解决方案5】:

    在 Python 3 中。

    >>> D1 = {2:3, 1:89, 4:5, 3:0}
    >>> for key in sorted(D1):
        print (key, D1[key])
    

    给予

    1 89
    2 3
    3 0
    4 5
    

    【讨论】:

      【解决方案6】:

      在这里,我找到了一些最简单的解决方案,可以使用 pprint 按键对 python dict 进行排序。 例如。

      >>> x = {'a': 10, 'cd': 20, 'b': 30, 'az': 99} 
      >>> print x
      {'a': 10, 'b': 30, 'az': 99, 'cd': 20}
      

      但是在使用 pprint 时它会返回排序后的字典

      >>> import pprint 
      >>> pprint.pprint(x)
      {'a': 10, 'az': 99, 'b': 30, 'cd': 20}
      

      【讨论】:

        【解决方案7】:

        找到另一种方式:

        import json
        print json.dumps(d, sort_keys = True)
        

        更新:
        1. 这也对嵌套对象进行排序(感谢@DanielF)。
        2. python 字典是无序的,因此仅适用于打印或分配给 str。

        【讨论】:

        • 但这也会对嵌套对象的键进行排序,这可能是不需要的。
        • 请注意,这仅对字典进行排序,而不是列表,例如dict.keys() 不会被排序,因为它是一个列表。
        【解决方案8】:

        Python 字典是无序的。通常,这不是问题,因为最常见的用例是进行查找。

        最简单的方法是创建一个collections.OrderedDict,按排序顺序插入元素。

        ordered_dict = collections.OrderedDict([(k, d[k]) for k in sorted(d.keys())])
        

        如果您需要迭代,正如上面其他人所建议的那样,最简单的方法是迭代排序的键。例子-

        打印按键排序的值:

        # create the dict
        d = {k1:v1, k2:v2,...}
        # iterate by keys in sorted order
        for k in sorted(d.keys()):
            value = d[k]
            # do something with k, value like print
            print k, value
        

        获取按键排序的值列表:

        values = [d[k] for k in sorted(d.keys())]
        

        【讨论】:

        • for k,value in sorted(d.items()): 更好:避免在循环中再次按键访问字典
        【解决方案9】:

        有许多 Python 模块提供字典实现,这些实现会自动按排序顺序维护键。考虑 sortedcontainers 模块,它是纯 Python 和 fast-as-C 实现。还有一个 performance comparison 与其他流行的选项相互进行基准测试。

        如果您需要在迭代的同时不断添加和删除键/值对,则使用有序 dict 是一个不合适的解决方案。

        >>> from sortedcontainers import SortedDict
        >>> d = {2:3, 1:89, 4:5, 3:0}
        >>> s = SortedDict(d)
        >>> s.items()
        [(1, 89), (2, 3), (3, 0), (4, 5)]
        

        SortedDict 类型还支持索引位置查找和删除,这是内置 dict 类型无法实现的。

        >>> s.iloc[-1]
        4
        >>> del s.iloc[2]
        >>> s.keys()
        SortedSet([1, 2, 4])
        

        【讨论】:

          【解决方案10】:

          简单地说:

          d = {2:3, 1:89, 4:5, 3:0}
          sd = sorted(d.items())
          
          for k,v in sd:
              print k, v
          

          输出:

          1 89
          2 3
          3 0
          4 5
          

          【讨论】:

          • sd 是元组列表,而不是字典。 (但仍然有用。)
          • 我相信你的打印语句需要()。打印 (k,v)
          • python 3 只需要 ()。print k, v 在 python 2 中工作得很好,因为 print 是关键字,而不是 python 2 中的函数。
          【解决方案11】:

          伙计们,你们把事情弄复杂了……真的很简单

          from pprint import pprint
          Dict={'B':1,'A':2,'C':3}
          pprint(Dict)
          

          输出是:

          {'A':2,'B':1,'C':3}
          

          【讨论】:

          • 赞成,因为我不知道 pprint 排序字典来显示它们,但是 OP 确实询问过从未排序到排序的字典“去”,即 OP 似乎想要在内存中保持排序的东西,也许对于一些需要排序键的算法
          • 此方法不允许链式赋值,因为 pprint 返回无。 >>> adict = {'B':1,'A':2,'C':3} >>> ppdict = pprint(adict) {'A': 2, 'B': 1, 'C': 3} >>> ppdict.type() Traceback(最近一次调用最后一次):文件“”,第 1 行,在 中 AttributeError:'NoneType' 对象没有属性 'type'
          【解决方案12】:

          2.7 中两种方法的时序比较表明它们几乎相同:

          >>> setup_string = "a = sorted(dict({2:3, 1:89, 4:5, 3:0}).items())"
          >>> timeit.timeit(stmt="[(k, val) for k, val in a]", setup=setup_string, number=10000)
          0.003599141953657181
          
          >>> setup_string = "from collections import OrderedDict\n"
          >>> setup_string += "a = OrderedDict({1:89, 2:3, 3:0, 4:5})\n"
          >>> setup_string += "b = a.items()"
          >>> timeit.timeit(stmt="[(k, val) for k, val in b]", setup=setup_string, number=10000)
          0.003581275490432745 
          

          【讨论】:

            【解决方案13】:
            l = dict.keys()
            l2 = l
            l2.append(0)
            l3 = []
            for repeater in range(0, len(l)):
                smallnum = float("inf")
                for listitem in l2:
                    if listitem < smallnum:
                        smallnum = listitem
                l2.remove(smallnum)
                l3.append(smallnum)
            l3.remove(0)
            l = l3
            
            for listitem in l:
                print(listitem)
            

            【讨论】:

            • 还有 14 个其他答案。您能否解释一下您的代码以及为什么它可能比其他解决方案更好?
            • Downvoted - 带有简短无意义变量名称 l、l2、l3 的非常不可读的代码。似乎是在不了解python标准函数的情况下尝试一种间接且低效的算法,并且在原始帖子中的小示例上进行测试时无论如何都不起作用。
            【解决方案14】:
            from operator import itemgetter
            # if you would like to play with multiple dictionaries then here you go:
            # Three dictionaries that are composed of first name and last name.
            user = [
                {'fname': 'Mo', 'lname': 'Mahjoub'},
                {'fname': 'Abdo', 'lname': 'Al-hebashi'},
                {'fname': 'Ali', 'lname': 'Muhammad'}
            ]
            #  This loop will sort by the first and the last names.
            # notice that in a dictionary order doesn't matter. So it could put the first name first or the last name first. 
            for k in sorted (user, key=itemgetter ('fname', 'lname')):
                print (k)
            
            # This one will sort by the first name only.
            for x in sorted (user, key=itemgetter ('fname')):
                print (x)
            

            【讨论】:

              【解决方案15】:

              有一种简单的方法可以对字典进行排序。

              根据您的问题,

              解决办法是:

              c={2:3, 1:89, 4:5, 3:0}
              y=sorted(c.items())
              print y
              

              (其中 c 是您的字典的名称。)

              这个程序给出以下输出:

              [(1, 89), (2, 3), (3, 0), (4, 5)]
              

              如你所愿。

              另一个例子是:

              d={"John":36,"Lucy":24,"Albert":32,"Peter":18,"Bill":41}
              x=sorted(d.keys())
              print x
              

              给出输出:['Albert', 'Bill', 'John', 'Lucy', 'Peter']

              y=sorted(d.values())
              print y
              

              给出输出:[18, 24, 32, 36, 41]

              z=sorted(d.items())
              print z
              

              给出输出:

              [('Albert', 32), ('Bill', 41), ('John', 36), ('Lucy', 24), ('Peter', 18)]
              

              因此,通过将其更改为键、值和项目,您可以按照自己的意愿进行打印。希望这会有所帮助!

              【讨论】:

                【解决方案16】:

                最简单的解决方案是你应该得到一个 dict 键的列表,按顺序排序,然后遍历 dict。例如

                a1 = {'a':1, 'b':13, 'd':4, 'c':2, 'e':30}
                a1_sorted_keys = sorted(a1, key=a1.get, reverse=True)
                for r in a1_sorted_keys:
                    print r, a1[r]
                

                以下将是输出(降序)

                e 30
                b 13
                d 4
                c 2
                a 1
                

                【讨论】:

                  【解决方案17】:

                  会生成你想要的:

                   D1 = {2:3, 1:89, 4:5, 3:0}
                  
                   sort_dic = {}
                  
                   for i in sorted(D1):
                       sort_dic.update({i:D1[i]})
                   print sort_dic
                  
                  
                  {1: 89, 2: 3, 3: 0, 4: 5}
                  

                  但这不是正确的方法,因为,它可能会在不同的字典中表现出不同的行为,这是我最近了解到的。因此,蒂姆在我在这里分享的查询的回复中提出了完美的方法。

                  from collections import OrderedDict
                  sorted_dict = OrderedDict(sorted(D1.items(), key=lambda t: t[0]))
                  

                  【讨论】:

                  • “使用不同的字典显示不同的行为”是什么意思? sorted 无法处理的“独特行为”是什么?
                  【解决方案18】:

                  我认为最简单的方法是按键对字典进行排序并将排序后的键:值对保存在新字典中。

                  dict1 = {'renault': 3, 'ford':4, 'volvo': 1, 'toyota': 2} 
                  dict2 = {}                  # create an empty dict to store the sorted values
                  for key in sorted(dict1.keys()):
                      if not key in dict2:    # Depending on the goal, this line may not be neccessary
                          dict2[key] = dict1[key]
                  

                  为了更清楚:

                  dict1 = {'renault': 3, 'ford':4, 'volvo': 1, 'toyota': 2} 
                  dict2 = {}                  # create an empty dict to store the sorted     values
                  for key in sorted(dict1.keys()):
                      if not key in dict2:    # Depending on the goal, this line may not be  neccessary
                          value = dict1[key]
                          dict2[key] = value
                  

                  【讨论】:

                    【解决方案19】:
                    dictionary = {1:[2],2:[],5:[4,5],4:[5],3:[1]}
                    
                    temp=sorted(dictionary)
                    sorted_dict = dict([(k,dictionary[k]) for i,k in enumerate(temp)])
                    
                    sorted_dict:
                             {1: [2], 2: [], 3: [1], 4: [5], 5: [4, 5]}
                    

                    【讨论】:

                      【解决方案20】:

                      对于 CPython/PyPy 3.6 以及任何 Python 3.7 或更高版本,这很容易通过以下方式完成:

                      >>> d = {2:3, 1:89, 4:5, 3:0}
                      >>> dict(sorted(d.items()))
                      {1: 89, 2: 3, 3: 0, 4: 5}
                      

                      【讨论】:

                      • 写同一件事的另一种方式是使用理解:{key:d[key] for key in sorted(d.keys())}
                      • 伟大的oneliner!我不知道那个新功能。它适用于我在 Python 3.6.8 上的 Centos 7 中。
                      • 这是一个很好的答案。但是不要试图通过将sorted{} 括起来来缩短它,就像在{sorted(d.items())} 中一样。那只会尝试创建一个集合。
                      • @flow2k 的答案(使用“comprehension”)可以简化为:{key:d[key] for key in sorted(d)},因为sorted(d) 返回 d 的键的排序列表
                      【解决方案21】:

                      Python 字典在 Python 3.6 之前是无序的。在 Python 3.6 的 CPython 实现中,字典保持插入顺序。 从 Python 3.7 开始,这将成为一种语言特性。

                      在 Python 3.6 (https://docs.python.org/3.6/whatsnew/3.6.html#whatsnew36-compactdict) 的更新日志中:

                      考虑了这个新实现的顺序保留方面 一个实现细节,不应依赖(这可能 将来会发生变化,但希望有这个新的字典 在更改之前的几个版本的语言中实现 语言规范要求所有当前的保持顺序的语义 以及未来的 Python 实现;这也有助于保存 向后兼容旧版本的语言 随机迭代顺序仍然有效,例如Python 3.5)。

                      在 Python 3.7 (https://docs.python.org/3.7/tutorial/datastructures.html#dictionaries) 的文档中:

                      对字典执行 list(d) 会返回所有使用的键的列表 在字典中,按插入顺序(如果要对其进行排序,只需使用 sorted(d) 代替)。

                      因此与以前的版本不同,您可以在 Python 3.6/3.7 之后对 dict 进行排序。如果要对包含子字典的嵌套字典进行排序,可以这样做:

                      test_dict = {'a': 1, 'c': 3, 'b': {'b2': 2, 'b1': 1}}
                      
                      def dict_reorder(item):
                          return {k: dict_reoder(v) if isinstance(v, dict) else v for k, v in sorted(item.items())}
                      
                      reordered_dict = dict_reorder(test_dict)
                      

                      https://gist.github.com/ligyxy/f60f0374defc383aa098d44cfbd318eb

                      【讨论】:

                      • 我喜欢这个,但你的字典理解中有sort_dict(),应该是dict_reoder()
                      【解决方案22】:

                      您可以根据您的问题通过按键对当前字典进行排序来创建新字典。

                      这是你的字典

                      d = {2:3, 1:89, 4:5, 3:0}
                      

                      通过使用 lambda 函数对该 d 进行排序来创建一个新的字典 d1

                      d1 = dict(sorted(d.items(), key = lambda x:x[0]))
                      

                      d1 应该是 {1:89, 2:3, 3:0, 4:5},根据 d 中的键排序。

                      【讨论】:

                      • 您甚至不需要指定排序键。 d1 = dict(sorted(d.items())) 可以正常工作
                      • 为什么这不是最佳答案?
                      【解决方案23】:

                      或者使用pandas

                      演示:

                      >>> d={'B':1,'A':2,'C':3}
                      >>> df=pd.DataFrame(d,index=[0]).sort_index(axis=1)
                         A  B  C
                      0  2  1  3
                      >>> df.to_dict('int')[0]
                      {'A': 2, 'B': 1, 'C': 3}
                      >>> 
                      

                      见:

                      Docs of this

                      Documentation of whole pandas

                      【讨论】:

                        【解决方案24】:

                        我想出了单行字典排序。

                        >> a = {2:3, 1:89, 4:5, 3:0}
                        >> c = {i:a[i] for i in sorted(a.keys())}
                        >> print(c)
                        {1: 89, 2: 3, 3: 0, 4: 5}
                        [Finished in 0.4s]
                        

                        希望这会有所帮助。

                        【讨论】:

                          【解决方案25】:

                          此函数将按其键对任何字典递归进行排序。也就是说,如果字典中的任何值也是字典,它也将按其键排序。如果您在 CPython 3.6 或更高版本上运行,则可以进行简单的更改以使用 dict 而不是 OrderedDict

                          from collections import OrderedDict
                          
                          def sort_dict(d):
                              items = [[k, v] for k, v in sorted(d.items(), key=lambda x: x[0])]
                              for item in items:
                                  if isinstance(item[1], dict):
                                      item[1] = sort_dict(item[1])
                              return OrderedDict(items)
                              #return dict(items)
                          

                          【讨论】:

                            【解决方案26】:

                            一个简单的方法:

                            d = {2:3, 1:89, 4:5, 3:0}
                            
                            s = {k : d[k] for k in sorted(d)}
                            
                            s
                            
                            Out[1]: {1: 89, 2: 3, 3: 0, 4: 5} 
                            

                            【讨论】:

                            • 仅适用于 python 3.7+,其中 dict 是 OrderedDict。
                            • @kwarnke Pedantic,但是 dict 与 Python 3.7+ 中的 OrderedDict 不同,虽然 dict is 当然在 3.7+ 中是有序的
                            【解决方案27】:

                            我的建议是这样,因为它允许您在添加项目时对字典进行排序或保持字典排序,并且将来可能需要添加项目:

                            从头开始构建dict。有第二个数据结构,一个列表,其中包含您的键列表。 bisect 包有一个 insort 函数,它允许插入一个排序的列表,或者在完全填充你的字典后对你的列表进行排序。现在,当您遍历您的 dict 时,您改为遍历列表以按顺序访问每个键,而无需担心 dict 结构的表示(不是为排序而设计的)。

                            【讨论】:

                              【解决方案28】:

                              对于问题的表述方式,这里的大多数答案都是正确的。

                              然而,考虑到事情应该是如何真正完成的,考虑到几十年和几十年的计算机科学,令我惊讶的是这里实际上只有one answer(来自@987654322 @user)建议使用排序的关联容器(sortedcontainers),它根据插入点处的键对元素进行排序。

                              这将避免每次调用sort(...)(至少O(N*log(N)),其中N 是元素数量)大量性能影响(从逻辑上讲,这适用于此处的所有此类解决方案建议使用sort(...))。考虑到对于所有此类解决方案,每次需要访问集合时都需要调用sort(...),因为它已通过添加修改AFTER /删除元素 ...

                              【讨论】:

                                【解决方案29】:

                                这里有很多答案已经展示了对 Python 字典进行排序的流行方法。我想我应该为那些从 Google 来到这里寻找非标准想法的人添加一些不太明显的方法。

                                示例字典:d = {2: 'c', 1: 'b', 0: 'a', 3: 'd'}

                                字典理解

                                # Converts to list, sorts, re-converts to dict
                                {k: v for k, v in sorted(list(d.items()))}
                                

                                使用 Lambda

                                排序并不总是严格按照升序或降序排列。更多条件排序,结合lamdas使用上述方法:

                                {k: v for k, v in sorted(d.items(), key=lambda v: ord(v[1]))}
                                

                                更多示例

                                这个帖子已经有足够多的好例子了。有关更多示例,以及在 Python 中排序字典的边缘情况和奇怪之处 check out this article

                                【讨论】:

                                • 对于字典列表理解,它对我不起作用我需要将 sorted(list(d)) 替换为 sorted(d.items())(在 python 3.8 上)
                                • @ihoupert 不只是你。我应该只是复制/粘贴我的版本,而不是尝试重新输入。它肯定需要在那里调用.items()
                                • 我遇到了类似的问题。感谢@ihoupert,我不得不使用.items()
                                【解决方案30】:

                                我发现对字典进行排序的一种简单方法是创建一个新字典,该方法基于您要排序的字典的已排序键:值项。 如果要对dict = {} 进行排序,请使用关联方法检索其所有项目,使用sorted() 函数对其进行排序,然后创建新字典。

                                这是使用字典理解的代码:

                                sorted_dict = {k:v for k,v in sorted(dict.items())}
                                

                                【讨论】:

                                  猜你喜欢
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 2021-08-20
                                  • 2013-03-14
                                  • 1970-01-01
                                  • 2014-04-11
                                  • 2021-12-20
                                  相关资源
                                  最近更新 更多