Why does a list not sort properly in Python as expected?
There are a couple of reasons why a list may not have sorted as expected in Python. Here are a couple of ways to diagnose the problem to help you check.
Here’s a quick list (no pun intended!) you can use to quickly check:
-
Are all elements within the list of the same data type?
-
Look at setting them to the same data type using the
key
parameter
-
Look at setting them to the same data type using the
-
Are you capturing the result of a
.sort()
method?-
Change this sort operation to the
sorted()
function
-
Change this sort operation to the
-
Are you sorting items with mixed case?
-
Apply the
key
parameter converting all items to.lower()
-
Apply the
-
Do you understand the
key
parameter?-
Extract the
lambda
function to check it works on elements in your list.
-
Extract the
-
Are you sorting in reverse?
-
Check the
reverse
parameter to your sort function.False
is the default setting it this parameter is not defined.
-
Check the
-
Are you sorting unicode characters?
-
Look to use a standard encoding type with the
key
parameter usinglambda x : x.encode('utf-8')
.
-
Look to use a standard encoding type with the
-
Are there any whitespace characters wrapping the elements?
-
Apply the
.strip()
string method to each element with thekey
parameter.
-
Apply the
Let’s explore each of these items in a little more detail with examples. Here are some reasons why your Python lists may not be sorting properly:
Data Type Inconsistencies
Understanding data types in Python is crucial to ensure your list sorts properly. Python supports several data types, such as integers, floats, and strings. When a list contains mixed data types, Python may not perform the sorting as expected.
How Python sorts data types differently depends on the items in the list. For example, a list with both integers and strings will raise a
TypeError
when you try to sort it. To avoid this issue, you must handle mixed data types in your lists properly.
Once way of doing this is to use the
key
parameter in the
sorted()
and
.sort()
list methods that can enable you to convert each of the elements within a list to the same data type:
>>> my_list = [2023, '2022', 2020.0]
>>> sorted(my_list, key=lambda x: str(x))
[2020.0, '2022', 2023]
Tips for handling mixed data types in lists include converting all items to a uniform data type or using a custom sorting function to order items based on your requirements.
You can read more about the
key
parameter in the
sorted()
and
.sort()
list method.
.sort()
Method Or
sorted()
Function Used Incorrectly
Python offers two main ways to sort lists: the
.sort()
method, which sorts a list in place, and the
sorted()
function, which returns a new sorted list without altering the original. Understanding the difference between these two options is essential for avoiding sorting issues.
Common mistakes when using
.sort()
and
sorted()
involve invoking them incorrectly, resulting in an unsorted list or unexpected changes to the original list. To ensure you’re using these functions properly, pay close attention to their syntax and return values.
One recent example where I made a mistake was expecting the
.sort()
list method to return a result (i.e. treating the sort operation like the
sorted()
function).
Here’s an example of this mistake:
>>> my_list = [3, 2, 1]
>>> my_sorted_list = my_list.sort()
>>> print(my_sorted_list)
None
What I should have done with the above code was use the
sorted()
function:
>>> my_list = [3, 2, 1]
>>> my_sorted_list = sorted(my_list)
>>> print(my_sorted_list)
[1, 2, 3]
That’s better!
It helps if you stick to one method when sorting a list as this helps you to minimise the impact of this type of error occurring. Of course, this error will also just creep in because you may just simply forget!
My preference is to use the
sorted()
method, as it doesn’t modify the original list.
Performing Case-Insensitive Sorting
When sorting string lists, Python’s default behaviour sorts uppercase letters before lowercase, potentially confusing the sort order.
To perform case-insensitive sorting, use the
key
argument with the
str.lower()
function as your key:
>>> surnames = ['de Longi', 'Deloitte', 'de Angelo']
>>> sorted(surnames)
['Deloitte', 'de Angelo', 'de Longi']
To fix this issue use the
key
parameter with a
lambda
function that converts each element in the list to lowercase:
>>> surnames = ['de Longi', 'Deloitte', 'de Angelo']
>>> sorted(surnames, key=lambda x: x.lower())
['de Angelo', 'de Longi', 'Deloitte']
Complex Custom
key
Parameter Used
The
key
parameter is a powerful parameter in your sort functions, however, if you don’t know what it’s doing then it could be causing all weird and wonderful types of sorting.
If you need to sort elements based on a specific attribute or function, you can use the
key
argument in the
.sort()
method or
sorted()
function. This will allow you to define a custom sort key that will be used to determine the order of elements.
However, if you don’t know what it’s doing then you could be in all manner of confusion. Extract the
lambda
function out from the
key
parameter and replace the variable
x
with a string to see what it does.
>>> my_list = [3, 'a', 1.0]
>>> sorted(my_list, key=lambda x: ord(str(x).lower()[0]))
[1.0, 3, 'a']
So to find out what on earth is happening in the
lambda
function extract it and swap out the variable used (in my case
x
) for a string or element in your list:
>>> ord(str('Test')[0])
116
You can even step through the function by examining the inner most functions by breaking it apart:
>>> str('Test').lower()
'test'
>>> 'test'[0]
't'
>>> ord('t')
Ah, ok. I’m finding the ordinal number of the first character of each element when it’s converted to a string.
Sorting In Reverse Order
Whether using the
.sort()
method or
sorted()
function, you can easily sort your list in reverse order by adding the
reverse=True
argument.
This will help you obtain a descending order when sorting your list items.
Check if you are using this parameter in your sort function. By default if the
reverse
parameter isn’t used then the sort function will sort the items in
ascending order
.
Setting
reverse=True
will sort the items in
descending order
.
Character Encoding Issues
Locale settings and character encoding can affect the way your Python list is sorted. You can use the
key
parameter and set each element to a specific encoding should it help.
>>> my_list = ['♠', 'Ω', 'и', '\u1118']
>>> sorted(my_list, key=lambda x: x.encode('utf-8'))
['Ω', 'и', 'ᄘ', '♠']
Python uses your system’s locale settings to determine appropriate sorting rules for characters. Checking and updating your locale settings may help resolve sorting problems related to special characters or accented letters.
Whitespace Characters
Check elements aren’t padded with whitespace as this can distort your results. Here’s an example where whitespace is giving incorrect sorts:
>>> my_list = [' 1', '\n2', '\t3']
>>> sorted(my_list)
['\t3', '\n2', ' 1']
Once again the
key
parameter can help by performing a clean on each data element by stripping away any leading and trailing whitespace.
>>> my_list = [' 1', '\n2', '\t3']
>>> sorted(my_list, key=lambda x: x.strip())
[' 1', '\n2', '\t3']
As you can see the above result produces the intended result by sorting the strings accordingly with the leading whitespace
" "
,
\t
(tabs) and
\n
(newline) characters.
Python List Not Sorting – Summary
If your Python sorting operation isn’t working out as you think perform the following checks to see if something isn’t set properly: data types; capturing result of
.sort()
; mixed cases; complex
key
function used; sorting in reverse; unicode characters; and leading whitespace characters.
To explore more about lists, read my next article on sorting a list alphabetically .