Version number comparison in Python

后端 未结 17 2015
小蘑菇
小蘑菇 2020-11-27 10:32

I want to write a cmp-like function which compares two version numbers and returns -1, 0, or 1 based on their compared va

相关标签:
17条回答
  • 2020-11-27 11:12

    i'm using this one on my project:

    cmp(v1.split("."), v2.split(".")) >= 0
    
    0 讨论(0)
  • 2020-11-27 11:13

    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))
    
    0 讨论(0)
  • 2020-11-27 11:13

    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.

    0 讨论(0)
  • 2020-11-27 11:15

    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;
    }
    
    0 讨论(0)
  • 2020-11-27 11:18
    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.

    0 讨论(0)
  • 2020-11-27 11:18

    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.

    0 讨论(0)
提交回复
热议问题