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

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']

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('.')])

I also solved this question using Python, although my version does some extra things, here is my code:

def answer(l):
    list1 = [] # this is the list for the nested strings
    for x in l:
        list1.append(x.split("."))
    list2 = [] # this is the same list as list one except everything  is an integer in order for proper sorting
    for y in list1:
        y = list(map(int, y))
        list2.append(y)
    list3 = sorted(list2) #this is the sorted list of of list 2
    FinalList = [] # this is the list that converts everything back to the way it was
    for a in list3:
        a = '.'.join(str(z) for z in a)
        FinalList.append(a)
    return FinalList

For versions there exist three things; Major, Minor, and the revision. What this does is that it organises it so that '1' will come before '1.0' which will come before '1.0.0'. Also, another plus, no need to import any libraries incase you don't have them, and it works with old versions of Python, this one was specifically meant for Version 2.7.6. Anyway, here are a few examples:

Inputs:
    (string list) l = ["1.1.2", "1.0", "1.3.3", "1.0.12", "1.0.2"]
Output:
    (string list) ["1.0", "1.0.2", "1.0.12", "1.1.2", "1.3.3"]

Inputs:
    (string list) l = ["1.11", "2.0.0", "1.2", "2", "0.1", "1.2.1", "1.1.1", "2.0"]
Output:
    (string list) ["0.1", "1.1.1", "1.2", "1.2.1", "1.11", "2", "2.0", "2.0.0"]

If you have any questions, just comment on the answer!

Tags:

Python