I have a list containing version strings, such as things:
versions_list = ["1.1.2", "1.0.0", "1.3.3", "1.0.12", "1.0.2"]
I would like to sort it, so the result would be something like this:
versions_list = ["1.0.0", "1.0.2", "1.0.12", "1.1.2", "1.3.3"]
The order of precedence for the digits should obviously be from left to right, and it should be descending. So 1.2.3
comes before 2.2.3
and 2.2.2
comes before 2.2.3
.
How do I do this in Python?
Python does not guarantee that the sort() function will work if a list contains items of different data types. As long as the items can be compared using the < comparison operator, an attempt will be made to sort the list. Otherwise, an error or exception may be generated.
sort() method sorts the elements of a list in ascending or descending order using the default < comparisons operator between items. Use the key parameter to pass the function name to be used for comparison instead of the default < operator. Set the reverse parameter to True, to get the list in descending order.
There will be three distinct ways to sort the nested lists. The first is to use Bubble Sort, the second is to use the sort() method, and the third is to use the sorted() method.
Use the Python List sort() method to sort a list in place. The sort() method sorts the string elements in alphabetical order and sorts the numeric elements from smallest to largest. Use the sort(reverse=True) to reverse the default sort order.
You can also use distutils.version
module of standard library:
from distutils.version import StrictVersion
versions = ["1.1.2", "1.0.0", "1.3.3", "1.0.12", "1.0.2"]
versions.sort(key=StrictVersion)
Gives you:
['1.0.0', '1.0.2', '1.0.12', '1.1.2', '1.3.3']
It can also handle versions with pre-release tags, for example:
versions = ["1.1", "1.1b1", "1.1a1"]
versions.sort(key=StrictVersion)
Gives you:
["1.1a1", "1.1b1", "1.1"]
Documentation: https://github.com/python/cpython/blob/3.2/Lib/distutils/version.py#L101
Split each version string to compare it as a list of integers:
versions_list.sort(key=lambda s: map(int, s.split('.')))
Gives, for your list:
['1.0.0', '1.0.2', '1.0.12', '1.1.2', '1.3.3']
In Python3 map
no longer returns a list
, So we need to wrap it in a list
call.
versions_list.sort(key=lambda s: list(map(int, s.split('.'))))
The alternative to map here is a list comprehension. See this post for more on list comprehensions.
versions_list.sort(key=lambda s: [int(u) for u in s.split('.')])
natsort proposes "natural sorting"; wich works very intuitively (in Python 3)
from natsort import natsorted
versions = ["1.1.2", "1.0.0", "1.3.3", "1.0.12", "1.0.2"]
natsorted(versions)
gives
['1.0.0', '1.0.2', '1.0.12', '1.1.2', '1.3.3']
but it works as well on complete package names with version number:
versions = ['version-1.9', 'version-2.0', 'version-1.11', 'version-1.10']
natsorted(versions)
gives
['version-1.9', 'version-1.10', 'version-1.11', 'version-2.0']
I think meanwhile, one would use packaging.version
for that.
Example:
from packaging.version import parse as parseVersion
versions = ['3.1', '0.7.1', '3.4.1', '0.7.7', '0.7.2', '3.3', '3.4.0', '0.7'
'0.7.5', '0.7.6', '3.0', '3.3.1', '0.7.3', '3.2', '0.7.4']
versions.sort(key = parseVersion)
Output:
['0.7', '0.7.1', '0.7.2', '0.7.3', '0.7.4', '0.7.5', '0.7.6',
'0.7.7', '3.0', '3.1', '3.2', '3.3', '3.3.1', '3.4.0', '3.4.1']
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With