Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing version numbers to real numbers

I would like to determine if one version number is greater than another. The version number could be any of the following:

4

4.2

4.22.2

4.2.2.233

...as the version number is beyond my control, so I couldn't say how many dots could actually exist in the number.

Since the number is not really a real number, I can't simply say,

Is 4.7 > 4.2.2

How can I go about converting a number, such as 4.2.2 into a real number that could be checked against another version number?

I would preferably like a ColdFusion solution, but the basic concept would also be fine.

like image 693
George Johnston Avatar asked Mar 02 '10 19:03

George Johnston


3 Answers

This is ripped from the plugin update code in Mango Blog, and updated a little bit. It should do exactly what you want. It returns 1 when argument 1 is greater, -1 when argument 2 is greater, and 0 when they are exact matches. (Note that 4.0.1 will be an exact match to 4.0.1.0)

It uses the CF list functions, instead of arrays, so you might see a small performance increase if you switched to arrays instead... but hey, it works!

function versionCompare( version1, version2 ){
    var len1 = listLen(arguments.version1, '.');
    var len2 = listLen(arguments.version2, '.');
    var i = 0;
    var piece1 = '';
    var piece2 = '';

    if (len1 gt len2){
        arguments.version2 = arguments.version2 & repeatString('.0', len1-len2);
    }else if (len2 gt len1){
        arguments.version1 = arguments.version1 & repeatString('.0', len2-len1);
    }

    for (i=1; i lte listLen(arguments.version1, '.'); i=i+1){
        piece1 = listGetAt(arguments.version1, i, '.');
        piece2 = listGetAt(arguments.version2, i, '.');

        if (piece1 neq piece2){
            if (piece1 gt piece2){
                return 1;
            }else{
                return -1;
            }
        }
    }

    //equal
    return 0;
}

Running your example test:

<cfoutput>#versionCompare('4.7', '4.2.2')#</cfoutput>

prints:

1

like image 77
Adam Tuttle Avatar answered Oct 28 '22 03:10

Adam Tuttle


If version 4 actually means 4.0.0, and version 4.2 actually means 4.2.0, you could easily convert the version to a simple integer.

suppose that every part of the version is between 0 and 99, then you could calculate an 'integer version' from X.Y.Z like this:

Version = X*100*100 + Y*100 + Z

If the ranges are bigger or smaller you could use factors higher or lower than 100.

Comparing the version then becomes easy.

like image 31
Patrick Avatar answered Oct 28 '22 01:10

Patrick


Parse each number separately and compare them iteratively.

if (majorVersion > 4 &&
    minorVersion > 2 &&
    revision > 2)
{
    // do something useful
}

// fail here

That's obviously not CF code, but you get the idea.

like image 1
Chris Avatar answered Oct 28 '22 01:10

Chris