How to sort dictionaries by keys in Python

后端 未结 7 1820
广开言路
广开言路 2020-12-15 05:28

Can anyone tell me how I can sort this:

{\'a\': [1, 2, 3], \'c\': [\'one\', \'two\'], \'b\': [\'blah\', \'bhasdf\', \'asdf\'], \'d\': [\'asdf\', \'wer\', \'a         


        
相关标签:
7条回答
  • 2020-12-15 06:10

    I will add my one cent to what others already explained. I happened to have the exact same problem in one specific case. I needed the output of my dictionary to always be the same for writing stable unit-tests.

    If by chance it is what you are trying to achieve, or some other output related task, you don't have to sort anything at all, just use pprint module, among other features it will sort dictionaries by keys.

    >>> d = {'a':1, 'b':2, 'c':3}
    >>> print d
    {'a': 1, 'c': 3, 'b': 2}
    
    >>> from pprint import pprint
    >>> pprint(d)
    {'a': 1, 'b': 2, 'c': 3}
    
    0 讨论(0)
  • 2020-12-15 06:11

    The correct answer is that if you want the items of a dictionary in a sorted order, you should use the sorted() function when you loop over the dictionary:

    for k, v in sorted(d.items()):
        print k, ':', v
    

    or

    for k in sorted(d):
       print d[k]
    

    Or similar.

    The OrderedDict mentioned is for dictionaries that have an order. And order is not the same as a sorting. You can create a sorted OrderedDict, yes, but as soon as you add a new key it is no longer sorted. So you would need to use sorted() anyway to sort it before each use or after each manipulation. The OrderedDict is therefore only slower and more memory intensive than an ordinary dictionary, while adding nothing you need.

    OrderedDict are not for sorted dictionaries, but for dictionaries where the items have some sort of ordering that is not a sorting. Such as if you want to show things in the order they were added, or if you want you users to be able to order things arbitrarily.

    Update: Further explanation

    Why is OrderedDict not a solution? Because an OrderedDict is ordered not sorted.

    Consider a standard dictionary:

    >>> d = {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5}
    

    It's not sorted, as we see below, 'c' will come before 'b'. It also has no order, if we add new things it appears what seems like random order:

    >>> d['g'] = 6
    >>> d['i'] = 8
    >>> d
    {'a': 0, 'c': 2, 'b': 1, 'e': 4, 'd': 3, 'g': 6, 'f': 5, 'i': 8}
    

    OK, so let's use an OrderedDict then:

    >>> o = OrderedDict(sorted({'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5}.items()))
    >>> o
    OrderedDict([('a', 0), ('b', 1), ('c', 2), ('d', 3), ('e', 4), ('f', 5)])
    

    Aha! Sorted! So OrderedDict works!? No.

    >>> o['i'] = 8
    >>> o['g'] = 6
    >>> o
    OrderedDict([('a', 0), ('b', 1), ('c', 2), ('d', 3), ('e', 4), ('f', 5), ('i', 8), ('g', 6)])
    

    What? The g ended up after the i?!? Why!? Because the OrderedDict is not sorted, it's ordered. It remembers the order you add things. Not the sorting. This means that every time you use it you need to sort it first. An OrderedDict will only stay sorted as long as you don't add keys to it. But if you aren't going to modify it, then you don't need a dict. You can just as well have a list. Which is what you get from sorted():

    >>> sorted(o.items())
    [('a', 0), ('b', 1), ('c', 2), ('d', 3), ('e', 4), ('f', 5), ('g', 6), ('i', 8)]
    

    But that works just as well with the standard dictionary, so the OrderedDictionary didn't help:

    >>> sorted(d.items())
    [('a', 0), ('b', 1), ('c', 2), ('d', 3), ('e', 4), ('f', 5), ('g', 6), ('i', 8)]
    

    Conclusion So each time you want to loop over the dictionary in a sorted way, you need to do:

    >>> for k in sorted(o):
    ...   print k, o[k]
    ... 
    a 0
    b 1
    c 2
    d 3
    e 4
    f 5
    g 6
    i 8
    

    And that is no matter what dictionary you use. OrderedDict doesn't really help you, because it doesn't care about sorting, just the order you add things in.

    0 讨论(0)
  • 2020-12-15 06:12

    It's worth noting that Python has a number of dictionary implementations that maintain the keys in sorted order. Consider the sortedcontainers module which is pure-Python and fast-as-C implementations. There's a performance comparison with other fast and feature-complete implementations benchmarked against one another.

    For example:

    >>> from sortedcontainers import SortedDict
    >>> d = {'a': [1, 2, 3], 'c': ['one', 'two'], 'b': ['blah', 'bhasdf', 'asdf'], 'd': ['asdf', 'wer', 'asdf', 'zxcv']}
    >>> s = SortedDict(**d)
    >>> s.keys()
    SortedSet(['a', 'b', 'c', 'd'])
    

    You can also entirely replace your use of dict with SortedDict as it supports fast get/set operations and sorted iterations of items by key.

    0 讨论(0)
  • 2020-12-15 06:19

    As the other answer mentioned, the order of a dictionary's keys is arbitrary and you shouldn't rely on it.

    If you're using Python 2.7 or 3.1 or later, try out collections.OrderedDict (2.7 docs; 3.1 docs; also see PEP 372). There's a link in the docs to a pure-Python version of OrderedDict that works on earlier Python versions.

    0 讨论(0)
  • 2020-12-15 06:22

    Here is a quick and easy function you can use to sort a dictionary by keys.

    Put this code in a separate file called sdict.py:

    def sortdict(dct):
        kys = dct.keys()
        kys.sort()
        from collections import OrderedDict
        d = OrderedDict()
        for x in kys: 
            for k, v in dct.iteritems():
                if (k == x):
                    d[k] = v
        return d
    

    Now, place this code into a separate file called test.py to test it with a sample dictionary:

    from sdict import sortdict
    import json
    dct = {'sizes':[32,28,42], 'dog':'schnauser', 'cat':'siamese', 'bird':'falcon'}
    dctx = sortdict(dct)
    print json.dumps(dctx) 
    

    And finally, call test.py from the command line:

    $ python test.py
    {"bird": "falcon", "cat": "siamese", "dog": "schnauser", "sizes": [32, 28, 42]}
    

    I'm only using json.dumps line to show you that it's an actual dictionary, and not just a string representation. You can also test it with the type() function for that matter.

    I included a nested list with numeric values in the sample dictionary to show that the function can handle more complex dictionaries, not just single-layer string-based dicts.

    The code is pretty straightforward, so it would be easy to modify it to sort by values, if that's your preference - although sorting by value would not make sense if some of the values are objects, like lists, tuples or other dicts.

    Admittedly, this only works in python 2.7 or later.

    Cheers,
    -=Cameron

    0 讨论(0)
  • 2020-12-15 06:26

    It may also be worth mentioning the nlargest routine in heapq. This sorts and returns the top N items. Depending upon what is actually required, this may be handy if you play with the key parameter. I mainly mention this since I discovered it a couple of nights ago and it did exactly what I was after. See PEP 0265 and Heapq.

    0 讨论(0)
提交回复
热议问题