Python Sorting

Sorting HOW TO


Python lists have a built-in list.sort() method that modifies the list in-place. There is also a sorted() built-in function that builds a new sorted list from an iterable.

In this document, we explore the various techniques for sorting data using Python.

sorted function


sorted(iterable, *, key=None, reverse=False)

Return a new sorted list from the items in iterable.

Has two optional arguments which must be specified as keyword arguments.

key specifies a function of one argument that is used to extract a comparison key from each element in iterable (for example, key=str.lower). The default value is None (compare the elements directly).

reverse is a boolean value. If set to True, then the list elements are sorted as if each comparison were reversed.

Use functools.cmp_to_key() to convert an old-style cmp function to a key function.

The built-in sorted() function is guaranteed to be stable. A sort is stable if it guarantees not to change the relative order of elements that compare equal — this is helpful for sorting in multiple passes (for example, sort by department, then by salary grade).

For sorting examples and a brief sorting tutorial, see Sorting HOW TO

Python Sorting


The easiest way to sort is with the sorted(list) function, which takes a list and returns a new list with those elements in sorted order. The original list is not changed.

a = [5, 1, 4, 3]
print sorted(a)
# output: [1, 3, 4, 5] 
print(a)
# output: [5, 1, 4, 3]

reverse=True argument


It’s most common to pass a list into the sorted() function, but in fact it can take as input any sort of iterable collection. The older list.sort() method is an alternative detailed below. The sorted() function seems easier to use compared to sort(), so I recommend using sorted().

The sorted() function can be customized through optional arguments. The sorted() optional argument reverse=True, e.g. sorted(list, reverse=True), makes it sort backwards.

example

mylist =  [4, 5, 3, 2, 1]
print(sorted(mylist))
# output: [1, 2, 3, 4, 5]
print(sorted(mylist, reverse=True))
# output: [5, 4, 3, 2, 1]

Key Functions


Both list.sort() and sorted() have a key parameter to specify a function to be called on each list element prior to making comparisons.

For more complex custom sorting, sorted() takes an optional "key=" specifying a “key” function that transforms each element before comparison. The key function takes in 1 value and returns 1 value, and the returned “proxy” value is used for the comparisons within the sort.

For example with a list of strings, specifying key=len (the built in len() function) sorts the strings by length, from shortest to longest. The sort calls len() for each string to get the list of proxy length values, and then sorts with those proxy values.

strs = ['ccc', 'aaaa', 'd', 'bb']
print(sorted(strs, key=len))
# output: ['d', 'bb', 'ccc', 'aaaa']

# or the same with lambda function
print(sorted(strs, key=lambda x: len(x)))
# output: ['d', 'bb', 'ccc', 'aaaa']

python sorted() key argument

another example:

strs = ['aa', 'BB', 'zz', 'CC']
print(sorted(strs, key=str.lower)) ## "key" argument specifying str.lower function to use for sorting proxy values ['aa', 'bb', 'cc', 'zz']
# output: ['aa', 'BB', 'CC', 'zz']

How to Order Dict Output in Python


Dicts are awesome, even for a beginner like me. What isn’t so awesome is trying to figure out how to list out their contents for the first time! Lists are easy enough but how on earth do you list out the key/value contents of a dict, let alone in any sort of order?

Listing the Contents of a Dict


Let’s start by simply listing out the dict contents. In the below example I have a dict stored in the ages variable.

ages = {'julian': 20, 'bob': 23, 'zack': 3, 'anthony': 95, 'daniel': 41}
for k, v in ages.items():
    print(k, v)

# output:
anthony 95
zack 3
julian 20
bob 23
daniel 41

Using a Lambda as Key Argument to Order the Output in Alphabetical Order


If you’re unsure of what a Lambda is, I strongly urge you to read this article by Dan Bader. It was my source for learning what they were and how to use them. It’s a great post!

The previous output is great but what if I wanted to print the ages data in alphabetical order? Not only do I need to sort it by the letter but also make sure I point my sorting method at the key in the dict. I can do this with a lambda!

First, let’s sort it alphabetically with the help of a lambda:

ages = {'julian': 20, 'bob': 23, 'zack': 3, 'anthony': 95, 'daniel': 41}
sorted(ages.items(), key=lambda x: x[0])
# output: [('anthony', 95), ('bob', 23), ('daniel', 41), ('julian', 20), ('zack', 3)]
  • First, note that we’re going to use sorted. This will sort everything between the () in ascending order. Run help(sorted) to see the available options to sorted. You’ll see that we can specify a key function to help sort the data.

  • ages.items() is called to break the ages dict up into the five individual items. Note that these “items” I’m referring to are actually tuples!

  • We then use a lambda function as the key to help sort. lambda x at this point will be the individual item in ages.items().

  • The function of lambda x is to sort by x[0] The contents of x[] is the key/value pair in the dict. For example, {‘julian’, 20}. The 0 indicates the first position in the pair, the key, which in this case is the name ‘julian’.

  • The output is then sorted by the key position in ascending, alphabetical order.

example 2:

ages = {'julian': 20, 'bob': 23, 'zack': 3, 'anthony': 95, 'daniel': 41}
sorted(ages.items(), key=lambda x: len(x[0]))
# output: [('bob', 23), ('zack', 3), ('julian', 20), ('daniel', 41), ('anthony', 95)]

Sorting the Output in Numerical Order


Now for the flip side. What if I wanted to sort it in numerical order which would be by the value in this case?

Identical as the above sort with one tiny change:

ages = {'julian': 20, 'bob': 23, 'zack': 3, 'anthony': 95, 'daniel': 41}
sorted(ages.items(), key=lambda x: x[1])
# output: [('zack', 3), ('julian', 20), ('bob', 23), ('daniel', 41), ('anthony', 95)]

Yep! All we do is change the lambda x function to point at position x[1], the value.

Storing the Sorted Output in a Dict


You’ll have noticed that we still have the output in a list and haven’t used print() yet. There’s a reason for that.

The thing is, it’s a lot harder and less Pythonic to print the output of a dict as a list, then iterate over that to get our friendlier print() output.

It’d be much better to iterate over the output like we did at the start of this post but to do that, our sorted() output would need to be a dict. How do we do that if we know sorted() always returns a list?

ages = {'julian': 20, 'bob': 23, 'zack': 3, 'anthony': 95, 'daniel': 41}
dict(sorted(ages.items(), key=lambda x: x[0]))
# output: {'anthony': 95, 'zack': 3, 'julian': 20, 'bob': 23, 'daniel': 41}

Bonus: Printing the Highest/Lowest Dict Item


Okay this is way out of scope for this post but I got playing and figured I’d add it in for good measure.

What if I wanted to list out the oldest chap in this list? Well, we don’t need to sort anything, we just need to know the max number/age right?

We use max and min python built-in functions.

ages = {'julian': 20, 'bob': 23, 'zack': 3, 'anthony': 95, 'daniel': 41}
max(ages.items(), key=lambda x: x[0])
# output: ('zack', 3)
max(ages.items(), key=lambda x: x[1])
# output: ('anthony', 95)
ages = {'julian': 20, 'bob': 23, 'zack': 3, 'anthony': 95, 'daniel': 41}
min(ages.items(), key=lambda x: x[0])   
# output: ('anthony', 95)
min(ages.items(), key=lambda x: x[1])
# output: ('zack', 3)

Python dict keeps insertion order from version 3.6. Ordered dictionary below python 3.6 is not supported.


resources:

https://developers.google.com/edu/python/sorting
https://pybit.es/dict-ordering.html
https://docs.python.org/3/howto/sorting.html
https://docs.python.org/3/library/functions.html
https://dbader.org/blog/python-lambda-functions

Share Comments
comments powered by Disqus