外部の依存関係を取りたくない場合のために、Python 3.x用に書かれた私の試みを示します。
rc
、rel
(場合によっては追加可能c
)は「リリース候補」と見なされ、バージョン番号を2つの部分に分割します。欠落している場合、2番目の部分の値は高くなります(999)。その他の文字は分割を生成し、base-36コードを介してサブ番号として扱われます。
import re
from itertools import chain
def compare_version(version1,version2):
'''compares two version numbers
>>> compare_version('1', '2') < 0
True
>>> compare_version('2', '1') > 0
True
>>> compare_version('1', '1') == 0
True
>>> compare_version('1.0', '1') == 0
True
>>> compare_version('1', '1.000') == 0
True
>>> compare_version('12.01', '12.1') == 0
True
>>> compare_version('13.0.1', '13.00.02') <0
True
>>> compare_version('1.1.1.1', '1.1.1.1') == 0
True
>>> compare_version('1.1.1.2', '1.1.1.1') >0
True
>>> compare_version('1.1.3', '1.1.3.000') == 0
True
>>> compare_version('3.1.1.0', '3.1.2.10') <0
True
>>> compare_version('1.1', '1.10') <0
True
>>> compare_version('1.1.2','1.1.2') == 0
True
>>> compare_version('1.1.2','1.1.1') > 0
True
>>> compare_version('1.2','1.1.1') > 0
True
>>> compare_version('1.1.1-rc2','1.1.1-rc1') > 0
True
>>> compare_version('1.1.1a-rc2','1.1.1a-rc1') > 0
True
>>> compare_version('1.1.10-rc1','1.1.1a-rc2') > 0
True
>>> compare_version('1.1.1a-rc2','1.1.2-rc1') < 0
True
>>> compare_version('1.11','1.10.9') > 0
True
>>> compare_version('1.4','1.4-rc1') > 0
True
>>> compare_version('1.4c3','1.3') > 0
True
>>> compare_version('2.8.7rel.2','2.8.7rel.1') > 0
True
>>> compare_version('2.8.7.1rel.2','2.8.7rel.1') > 0
True
'''
chn = lambda x:chain.from_iterable(x)
def split_chrs(strings,chars):
for ch in chars:
strings = chn( [e.split(ch) for e in strings] )
return strings
split_digit_char=lambda x:[s for s in re.split(r'([a-zA-Z]+)',x) if len(s)>0]
splt = lambda x:[split_digit_char(y) for y in split_chrs([x],'.-_')]
def pad(c1,c2,f='0'):
while len(c1) > len(c2): c2+=[f]
while len(c2) > len(c1): c1+=[f]
def base_code(ints,base):
res=0
for i in ints:
res=base*res+i
return res
ABS = lambda lst: [abs(x) for x in lst]
def cmp(v1,v2):
c1 = splt(v1)
c2 = splt(v2)
pad(c1,c2,['0'])
for i in range(len(c1)): pad(c1[i],c2[i])
cc1 = [int(c,36) for c in chn(c1)]
cc2 = [int(c,36) for c in chn(c2)]
maxint = max(ABS(cc1+cc2))+1
return base_code(cc1,maxint) - base_code(cc2,maxint)
v_main_1, v_sub_1 = version1,'999'
v_main_2, v_sub_2 = version2,'999'
try:
v_main_1, v_sub_1 = tuple(re.split('rel|rc',version1))
except:
pass
try:
v_main_2, v_sub_2 = tuple(re.split('rel|rc',version2))
except:
pass
cmp_res=[cmp(v_main_1,v_main_2),cmp(v_sub_1,v_sub_2)]
res = base_code(cmp_res,max(ABS(cmp_res))+1)
return res
import random
from functools import cmp_to_key
random.shuffle(versions)
versions.sort(key=cmp_to_key(compare_version))