I want to write a cmp
-like function which compares two version numbers and returns -1
, 0
, or 1
based on their compared va
i'm using this one on my project:
cmp(v1.split("."), v2.split(".")) >= 0
Is reuse considered elegance in this instance? :)
# 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))
Years later, but stil this question is on the top.
Here is my version sort function. It splits version into numbers and non-numbers sections. Numbers are compared as int
rest as str
(as parts of list items).
def sort_version_2(data):
def key(n):
a = re.split(r'(\d+)', n)
a[1::2] = map(int, a[1::2])
return a
return sorted(data, key=lambda n: key(n))
You can use function key
as kind of custom Version
type with compare operators. If out really want to use cmp
you can do it like in this example: https://stackoverflow.com/a/22490617/9935708
def Version(s):
s = re.sub(r'(\.0*)*$', '', s) # to avoid ".0" at end
a = re.split(r'(\d+)', s)
a[1::2] = map(int, a[1::2])
return a
def mycmp(a, b):
a, b = Version(a), Version(b)
return (a > b) - (a < b) # DSM's answer
Test suite passes.
This is my solution (written in C, sorry). I hope you'll find it useful
int compare_versions(const char *s1, const char *s2) {
while(*s1 && *s2) {
if(isdigit(*s1) && isdigit(*s2)) {
/* compare as two decimal integers */
int s1_i = strtol(s1, &s1, 10);
int s2_i = strtol(s2, &s2, 10);
if(s1_i != s2_i) return s1_i - s2_i;
} else {
/* compare as two strings */
while(*s1 && !isdigit(*s1) && *s2 == *s1) {
s1++;
s2++;
}
int s1_i = isdigit(*s1) ? 0 : *s1;
int s2_i = isdigit(*s2) ? 0 : *s2;
if(s1_i != s2_i) return s1_i - s2_i;
}
}
return 0;
}
from distutils.version import StrictVersion
def version_compare(v1, v2, op=None):
_map = {
'<': [-1],
'lt': [-1],
'<=': [-1, 0],
'le': [-1, 0],
'>': [1],
'gt': [1],
'>=': [1, 0],
'ge': [1, 0],
'==': [0],
'eq': [0],
'!=': [-1, 1],
'ne': [-1, 1],
'<>': [-1, 1]
}
v1 = StrictVersion(v1)
v2 = StrictVersion(v2)
result = cmp(v1, v2)
if op:
assert op in _map.keys()
return result in _map[op]
return result
Implement for php version_compare
, except "=". Because it's ambiguous.
The most difficult to read solution, but a one-liner nevertheless! and using iterators to be fast.
next((c for c in imap(lambda x,y:cmp(int(x or 0),int(y or 0)),
v1.split('.'),v2.split('.')) if c), 0)
that is for Python2.6 and 3.+ btw, Python 2.5 and older need to catch the StopIteration.