Sort list while pushing None values to the end

PythonListSortingNonetype

Python Problem Overview


I have a homogeneous list of objects with None, but it can contain any type of values. Example:

>>> l = [1, 3, 2, 5, 4, None, 7]
>>> sorted(l)
[None, 1, 2, 3, 4, 5, 7]
>>> sorted(l, reverse=True)
[7, 5, 4, 3, 2, 1, None]

Is there a way without reinventing the wheel to get the list sorted the usual python way, but with None values at the end of the list, like that:

[1, 2, 3, 4, 5, 7, None]

I feel like here can be some trick with "key" parameter

Python Solutions


Solution 1 - Python

>>> l = [1, 3, 2, 5, 4, None, 7]
>>> sorted(l, key=lambda x: (x is None, x))
[1, 2, 3, 4, 5, 7, None]

This constructs a tuple for each element in the list, if the value is None the tuple with be (True, None), if the value is anything else it will be (False, x) (where x is the value). Since tuples are sorted item by item, this means that all non-None elements will come first (since False < True), and then be sorted by value.

Solution 2 - Python

Try this:

sorted(l, key=lambda x: float('inf') if x is None else x)

Since infinity is larger than all integers, None will always be placed last.

Solution 3 - Python

I created a function that expands on the answer by Andrew Clark and the comment by tutuDajuju.

def sort(myList, reverse = False, sortNone = False):
	"""Sorts a list that may or may not contain None.
	Special thanks to Andrew Clark and tutuDajuju for how to sort None on https://stackoverflow.com/questions/18411560/python-sort-list-with-none-at-the-end

	reverse (bool) - Determines if the list is sorted in ascending or descending order

	sortNone (bool) - Determines how None is sorted
		- If True: Will place None at the beginning of the list
		- If False: Will place None at the end of the list
		- If None: Will remove all instances of None from the list

	Example Input: sort([1, 3, 2, 5, 4, None, 7])
	Example Input: sort([1, 3, 2, 5, 4, None, 7], reverse = True)
	Example Input: sort([1, 3, 2, 5, 4, None, 7], reverse = True, sortNone = True)
	Example Input: sort([1, 3, 2, 5, 4, None, 7], sortNone = None)
	"""

	return sorted(filter(lambda item: True if (sortNone != None) else (item != None), myList), 
		key = lambda item: (((item is None)     if (reverse) else (item is not None)) if (sortNone) else
							((item is not None) if (reverse) else (item is None)), item), 
		reverse = reverse)

Here is an example of how you can run it:

myList = [1, 3, 2, 5, 4, None, 7]
print(sort(myList))
print(sort(myList, reverse = True))
print(sort(myList, sortNone = True))
print(sort(myList, reverse = True, sortNone = True))
print(sort(myList, sortNone = None))
print(sort(myList, reverse = True, sortNone = None))

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNikolai GolubView Question on Stackoverflow
Solution 1 - PythonAndrew ClarkView Answer on Stackoverflow
Solution 2 - PythonSethMMortonView Answer on Stackoverflow
Solution 3 - PythonKadeView Answer on Stackoverflow