Joh*_*rra 95 python string-comparison
我想写一个cmp样功能,比较两个版本号,并返回-1,0或1根据自己的比较valuses.
-1如果版本A早于版本B,则返回0如果版本A和B是等价的1如果版本A比版本B更新,则返回每个子部分应该被解释为一个数字,因此1.10> 1.1.
期望的功能输出是
mycmp('1.0', '1') == 0
mycmp('1.0.0', '1') == 0
mycmp('1', '1.0.0.1') == -1
mycmp('12.10', '11.0.0.0.0') == 1
...
Run Code Online (Sandbox Code Playgroud)
这是我的实施,开放改进:
def mycmp(version1, version2):
parts1 = [int(x) for x in version1.split('.')]
parts2 = [int(x) for x in version2.split('.')]
# fill up the shorter version with zeros ...
lendiff = len(parts1) - len(parts2)
if lendiff > 0:
parts2.extend([0] * lendiff)
elif lendiff < 0:
parts1.extend([0] * (-lendiff))
for i, p in enumerate(parts1):
ret = cmp(p, parts2[i])
if ret: return ret
return 0
Run Code Online (Sandbox Code Playgroud)
我正在使用Python 2.4.5顺便说一句.(安装在我工作的地方......).
这是一个可以使用的小型"测试套件"
assert mycmp('1', '2') == -1
assert mycmp('2', '1') == 1
assert mycmp('1', '1') == 0
assert mycmp('1.0', '1') == 0
assert mycmp('1', '1.000') == 0
assert mycmp('12.01', '12.1') == 0
assert mycmp('13.0.1', '13.00.02') == -1
assert mycmp('1.1.1.1', '1.1.1.1') == 0
assert mycmp('1.1.1.2', '1.1.1.1') == 1
assert mycmp('1.1.3', '1.1.3.000') == 0
assert mycmp('3.1.1.0', '3.1.2.10') == -1
assert mycmp('1.1', '1.10') == -1
Run Code Online (Sandbox Code Playgroud)
bra*_*ers 271
用Python怎么样distutils.version.StrictVersion?
>>> from distutils.version import StrictVersion
>>> StrictVersion('10.4.10') > StrictVersion('10.4.9')
True
Run Code Online (Sandbox Code Playgroud)
所以对你的cmp功能:
>>> cmp = lambda x, y: StrictVersion(x).__cmp__(y)
>>> cmp("10.4.10", "10.4.11")
-1
Run Code Online (Sandbox Code Playgroud)
如果要比较更复杂的版本号distutils.version.LooseVersion将更有用,但请务必仅比较相同的类型.
>>> from distutils.version import LooseVersion, StrictVersion
>>> LooseVersion('1.4c3') > LooseVersion('1.3')
True
>>> LooseVersion('1.4c3') > StrictVersion('1.3') # different types
False
Run Code Online (Sandbox Code Playgroud)
LooseVersion 不是最聪明的工具,很容易被欺骗:
>>> LooseVersion('1.4') > LooseVersion('1.4-rc1')
False
Run Code Online (Sandbox Code Playgroud)
要想成功使用这个品种,您需要走出标准库并使用setuptools的解析实用程序parse_version.
>>> from pkg_resources import parse_version
>>> parse_version('1.4') > parse_version('1.4-rc2')
True
Run Code Online (Sandbox Code Playgroud)
因此,根据您的具体用例,您需要确定内置distutils工具是否足够,或者是否有必要将其添加为依赖项setuptools.
gnu*_*nud 36
删除字符串中不感兴趣的部分(尾随零和点),然后比较数字列表.
import re
def mycmp(version1, version2):
def normalize(v):
return [int(x) for x in re.sub(r'(\.0+)*$','', v).split(".")]
return cmp(normalize(version1), normalize(version2))
Run Code Online (Sandbox Code Playgroud)
编辑:与PärWieslander相同的方法,但更紧凑.
一些测试,感谢这篇文章:
assert mycmp("1", "1") == 0
assert mycmp("2.1", "2.2") < 0
assert mycmp("3.0.4.10", "3.0.4.2") > 0
assert mycmp("4.08", "4.08.01") < 0
assert mycmp("3.2.1.9.8144", "3.2") > 0
assert mycmp("3.2", "3.2.1.9.8144") < 0
assert mycmp("1.2", "2.1") < 0
assert mycmp("2.1", "1.2") > 0
assert mycmp("5.6.7", "5.6.7") == 0
assert mycmp("1.01.1", "1.1.1") == 0
assert mycmp("1.1.1", "1.01.1") == 0
assert mycmp("1", "1.0") == 0
assert mycmp("1.0", "1") == 0
assert mycmp("1.0", "1.0.1") < 0
assert mycmp("1.0.1", "1.0") > 0
assert mycmp("1.0.2.0", "1.0.2") == 0
Run Code Online (Sandbox Code Playgroud)
con*_*nny 30
被重用认为优雅在这种情况下?:)
# pkg_resources is in setuptools
# See http://peak.telecommunity.com/DevCenter/PkgResources#parsing-utilities
def mycmp(a, b):
from pkg_resources import parse_version as V
return cmp(V(a),V(b))
Run Code Online (Sandbox Code Playgroud)
Ant*_*sma 12
无需迭代版本元组.列表和元组上的内置比较运算符已经完全按照您的需要运行.您只需要将版本列表零扩展到相应的长度.使用python 2.6,您可以使用izip_longest填充序列.
from itertools import izip_longest
def version_cmp(v1, v2):
parts1, parts2 = [map(int, v.split('.')) for v in [v1, v2]]
parts1, parts2 = zip(*izip_longest(parts1, parts2, fillvalue=0))
return cmp(parts1, parts2)
Run Code Online (Sandbox Code Playgroud)
对于较低版本,需要一些地图hackery.
def version_cmp(v1, v2):
parts1, parts2 = [map(int, v.split('.')) for v in [v1, v2]]
parts1, parts2 = zip(*map(lambda p1,p2: (p1 or 0, p2 or 0), parts1, parts2))
return cmp(parts1, parts2)
Run Code Online (Sandbox Code Playgroud)
Pär*_*der 10
这比你的建议更紧凑.我没有用零填充较短的版本,而是在拆分后从版本列表中删除尾随零.
def normalize_version(v):
parts = [int(x) for x in v.split(".")]
while parts[-1] == 0:
parts.pop()
return parts
def mycmp(v1, v2):
return cmp(normalize_version(v1), normalize_version(v2))
Run Code Online (Sandbox Code Playgroud)
使用正则表达式删除尾随.0和.00,拆分并使用cmp函数正确比较数组.
def mycmp(v1,v2):
c1=map(int,re.sub('(\.0+)+\Z','',v1).split('.'))
c2=map(int,re.sub('(\.0+)+\Z','',v2).split('.'))
return cmp(c1,c2)
Run Code Online (Sandbox Code Playgroud)
当然,如果你不介意长线,你可以将它转换为单线