我正在浏览一个包含卵的目录,以便将这些卵添加到sys.path。如果目录中有相同的.egg的两个版本,我只想添加最新的版本。

我有一个正则表达式r ^ (? P < eggName > \ w +) - (? P < eggVersion > (\ d \.]+)-.+\.Egg $从文件名中提取名称和版本。问题是比较版本号,它是一个像2.3.1这样的字符串。

因为我比较字符串,2排序超过10,但这是不正确的版本。

>>> "2.3.1" > "10.1.1"
True

我可以做一些拆分、解析、转换为int等,最终我将得到一个变通方法。但这是Python,不是Java。是否有一种优雅的方法来比较版本字符串?


当前回答

使用python增加版本

def increment_version(version):
    version = version.split('.')
    if int(version[len(version) - 1]) >= 99:
        version[len(version) - 1] = '0'
        version[len(version) - 2] = str(int(version[len(version) - 2]) + 1)
    else:
        version[len(version) - 1] = str(int(version[len(version) - 1]) + 1)
    return '.'.join(version)

version = "1.0.0"
version_type_2 = "1.0"
print("old version",version ,"new version",increment_version(version))
print("old version",version_type_2 ,"new version",increment_version(version_type_2))

其他回答

类似于标准strverscmp,类似于Mark Byers的解决方案,但使用findall而不是split来避免空大小写。

import re
num_split_re = re.compile(r'([0-9]+|[^0-9]+)')

def try_int(i, fallback=None):
    try:
        return int(i)
    except ValueError:
        pass
    except TypeError:
        pass
    return fallback

def ver_as_list(a):
    return [try_int(i, i) for i in num_split_re.findall(a)]

def strverscmp_lt(a, b):
    a_ls = ver_as_list(a)
    b_ls = ver_as_list(b)
    return a_ls < b_ls

有包装包可用,这将允许您比较版本按照PEP-440,以及遗留版本。

>>> from packaging.version import Version, LegacyVersion
>>> Version('1.1') < Version('1.2')
True
>>> Version('1.2.dev4+deadbeef') < Version('1.2')
True
>>> Version('1.2.8.5') <= Version('1.2')
False
>>> Version('1.2.8.5') <= Version('1.2.8.6')
True

旧版本支持:

>>> LegacyVersion('1.2.8.5-5-gdeadbeef')
<LegacyVersion('1.2.8.5-5-gdeadbeef')>

比较遗留版本和PEP-440版本。

>>> LegacyVersion('1.2.8.5-5-gdeadbeef') < Version('1.2.8.6')
True

将版本字符串转换为元组并从那里开始有什么问题?对我来说已经够优雅了

>>> (2,3,1) < (10,1,1)
True
>>> (2,3,1) < (10,1,1,1)
True
>>> (2,3,1,10) < (10,1,1,1)
True
>>> (10,3,1,10) < (10,1,1,1)
False
>>> (10,3,1,10) < (10,4,1,1)
True

@kindall的解决方案是一个简单的例子,说明代码看起来有多好。

使用python增加版本

def increment_version(version):
    version = version.split('.')
    if int(version[len(version) - 1]) >= 99:
        version[len(version) - 1] = '0'
        version[len(version) - 2] = str(int(version[len(version) - 2]) + 1)
    else:
        version[len(version) - 1] = str(int(version[len(version) - 1]) + 1)
    return '.'.join(version)

version = "1.0.0"
version_type_2 = "1.0"
print("old version",version ,"new version",increment_version(version))
print("old version",version_type_2 ,"new version",increment_version(version_type_2))

这是一个用于比较三个版本号的紧凑代码。注意,这里的字符串比较对所有对都失败了。

from itertools import permutations

for v1, v2 in permutations(["3.10.21", "3.10.3", "3.9.9"], 2):
    print(f"\nv1 = {v1}, v2 = {v2}")
    print(f"v1 < v2      version.parse(v1) < version.parse(v2)")
    print(f"{v1 < v2}         {version.parse(v1) < version.parse(v2)}")

这给了我们:

v1='3.10.21', v2='3.10.3'
v1 < v2      version.parse(v1) < version.parse(v2)
True         False

v1='3.10.21', v2='3.9.9'
v1 < v2      version.parse(v1) < version.parse(v2)
True         False

v1='3.10.3', v2='3.10.21'
v1 < v2      version.parse(v1) < version.parse(v2)
False         True

v1='3.10.3', v2='3.9.9'
v1 < v2      version.parse(v1) < version.parse(v2)
True         False

v1='3.9.9', v2='3.10.21'
v1 < v2      version.parse(v1) < version.parse(v2)
False         True

v1='3.9.9', v2='3.10.3'
v1 < v2      version.parse(v1) < version.parse(v2)
False         True

Permutations (iterable, 2)给出了一个可迭代对象的所有长度为2的排列。例如,

list(permutations('ABC', 2))

给了我们[(A, B), (' A ', ' C '), (A, B),(“B”、“C”)(“C”,“A”),(“C”、“B”)]。