对点分隔的数字列表进行排序,例如软件版本


75

我有一个包含版本字符串的列表,例如:

versions_list = ["1.1.2", "1.0.0", "1.3.3", "1.0.12", "1.0.2"]

我想对其进行排序,所以结果将是这样的:

versions_list = ["1.0.0", "1.0.2", "1.0.12", "1.1.2", "1.3.3"]

数字的优先顺序显然应该从左到右,并且应该是降序。所以1.2.3来之前2.2.32.2.2来之前2.2.3

如何在Python中执行此操作?


Answers:


94

拆分每个版本字符串,以将其作为整数列表进行比较:

versions_list.sort(key=lambda s: map(int, s.split('.')))

给出,作为您的清单:

['1.0.0', '1.0.2', '1.0.12', '1.1.2', '1.3.3']

在Python3中map不再返回a list,因此我们需要将其包装在list调用中

versions_list.sort(key=lambda s: list(map(int, s.split('.'))))

映射的替代方法是列表理解。有关列表理解的更多信息,请参见这篇文章

versions_list.sort(key=lambda s: [int(u) for u in s.split('.')])

对于正则表达式解决方案,您只需将s替换为返回所需组的表达式即可。例如:lambda s:map(int,re.search(myre,s).groups [0] .split('。'))
Andrew Cox

4
这是纯粹的优雅。
Balthazar Rouberol 2013年

排序返回无,但列表已排序。
themadmax

3
该键函数在Python 3中不起作用,因为在Python 3中map返回的是迭代器,而不是列表。但这在以下两个版本中都适用:key=lambda s: [int(u) for u in s.split('.')])
下午16年

建议您假设读者正在使用Python 3,并在需要时将python 2作为例外。
macetw '18

140

您还可以使用distutils.version标准库的模块:

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)

给你:

['1.0.0', '1.0.2', '1.0.12', '1.1.2', '1.3.3']

它还可以处理带有预发布标签的版本,例如:

versions = ["1.1", "1.1b1", "1.1a1"]
versions.sort(key=StrictVersion)

给你:

["1.1a1", "1.1b1", "1.1"]

文档:https : //github.com/python/cpython/blob/3.2/Lib/distutils/version.py#L101


1
似乎比Eli的解决方案更具pythonic风格。
Vojta Rylko,2010年

22
还有distutils.version.LooseVersion,它的版本号以字母['1.0b','1.0.2-final']等结尾,还是更宽容一些-我更喜欢此版本,因为StrictVersion似乎更多面向Python distutils特定的版本字符串,LooseVersion可满足您在野外看到的更广泛的潜在版本字符串。
synthesizerpatel

StrictVersion不处理诸如“ 9.20.00.0”之类的版本:返回了无效的版本号。我想知道是否但这是因为实际版本显示为u'9.20.00.0'... ??? 也许这需要解码为UTF-8。
IAbstract

3
如果需要更多自由度,可以在StrictVersion上使用distutils.version.LooseVersion。参见epydoc.sourceforge.net/stdlib/…–
ferdy

不幸的是,即使您无法从Docker注册表中恢复登录,它也LooseVersion不起作用['0.1.0', 'latest']。为此,我在此页面上使用了natsort答案。
布鲁诺·布罗诺斯基

16

natsort提出“自然排序”;wich非常直观(在Python 3中)

from natsort import natsorted
versions = ["1.1.2", "1.0.0", "1.3.3", "1.0.12", "1.0.2"]
natsorted(versions)

['1.0.0', '1.0.2', '1.0.12', '1.1.2', '1.3.3']

但在带有版本号的完整软件包名称上也可以正常使用:

versions = ['version-1.9', 'version-2.0', 'version-1.11', 'version-1.10']
natsorted(versions)

['version-1.9', 'version-1.10', 'version-1.11', 'version-2.0']

如何用字典列表实现这一点?即[['env':'REE','version':'API-1.1.12'},{'env':'REE','version':'API-1.2.0'}]根据版本密钥排序。
Vijaysinh Parmar

1

我也使用Python解决了这个问题,尽管我的版本做了一些额外的事情,但这是我的代码:

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

对于版本,存在三件事;主要,次要和修订。这是因为它组织了它,使它'1''1.0'于先后'1.0.0'。另外,还有一个优点是,如果您没有库,则无需导入任何库,并且它适用于旧版本的Python,该库专门用于2.7.6版。无论如何,这里有一些例子:

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

如有任何疑问,请对答案发表评论!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.