Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting a list of dot-separated numbers, like software versions

Tags:

python

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?

like image 956
Zack Avatar asked Apr 04 '10 09:04

Zack


People also ask

Can you sort a list with different data types?

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.

How do you sort a list of elements?

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.

Can you sort a nested list?

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.

How do you sort a numbered list in Python?

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.


4 Answers

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

like image 150
andreypopp Avatar answered Oct 23 '22 05:10

andreypopp


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('.')])
like image 24
Eli Bendersky Avatar answered Oct 23 '22 04:10

Eli Bendersky


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']
like image 28
Chris Maes Avatar answered Oct 23 '22 03:10

Chris Maes


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']
like image 2
Tobias Leupold Avatar answered Oct 23 '22 05:10

Tobias Leupold