简体   繁体   中英

sorting version numbers stored as string in an array

Say I have an array like this:

let arr = ["1.2.5", "1", "10", "2.0.4", "3.3.3.3"];

What would be the best way to sort this and get result like this:
 let arr = ["1", "1.2.5", "2.0.4", "3.3.3.3", "10"];

First I thought of converting each item in the array into 'float' may work but then multiple decimals won't give expected results.

I can also go for a for loop and doing stuff like item.split(".") and then check one by one, but I do not think this is the best way.

Any suggestions, please?

You could use String#localeCompare with options

sensitivity

Which differences in the strings should lead to non-zero result values. Possible values are:

  • "base" : Only strings that differ in base letters compare as unequal. Examples: a ≠ b , a = á , a = A .
  • "accent" : Only strings that differ in base letters or accents and other diacritic marks compare as unequal. Examples: a ≠ b , a ≠ á , a = A .
  • "case" : Only strings that differ in base letters or case compare as unequal. Examples: a ≠ b , a = á , a ≠ A .
  • "variant" : Strings that differ in base letters, accents and other diacritic marks, or case compare as unequal. Other differences may also be taken into consideration. Examples: a ≠ b , a ≠ á , a ≠ A .

The default is "variant" for usage "sort"; it's locale dependent for usage "search".

numeric

Whether numeric collation should be used, such that "1" < "2" < "10". Possible values are true and false ; the default is false . This option can be set through an options property or through a Unicode extension key; if both are provided, the options property takes precedence. Implementations are not required to support this property.

 var array = ["1.2.5", "1", "10", "2.0.4", "3.3.3.3"]; array.sort(function (a,b) { return a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' }); }); console.log(array);

function compare(a, b) {
    var aSplit = a.split(".");
    var bSplit = b.split(".");


    var length = Math.min(aSplit.length, bSplit.length);
    for (var i = 0; i < length; ++i) {
        if (parseInt(aSplit[i]) < parseInt(bSplit[i])) {
            return -1;
        } else if (parseInt(aSplit[i]) > parseInt(bSplit[i])) {
            return 1;
        }
    }

    if (aSplit.length < bSplit.length) {
        return -1;
    } else if (aSplit.length > bSplit.length) {
        return 1;
    }

    return 0;
}

You can use it like: arr.sort((a, b) => compare(a, b));

Here is my solution (uses ES6 syntax)

 const arr = ["1.2.5", "1", "10", "2.0.4", "3.3.3.3"]; const result = arr.map((n) => n.split('.').map((c) => c.padStart(10, '0')).join('.')).sort().map((n) => n.split('.').map((c) => +c).join('.')) console.log(result);

var arr = ["1.2.5", "1", "10", "2.0.4", "3.3.3.3"];

 var arr = ["1.2.5", "1", "10", "2.0.4", "3.3.3.3"]; console.log(arr.sort(function(a,b){ var arr1 = a.split('.'); var arr2 = b.split('.'); var maxlen = Math.max(arr1.length,arr2.length); var i; for(i = 0;i<maxlen;i++){ var i1 = parseInt(arr1[i] || 0) var i2 = parseInt(arr2[i] || 0) if(i1 < i2){ return -1; } else if(i1 > i2){ return 1; } } return 0; }));

  • sort 1.0a notation correct
  • use native localeCompare to sort 1.090 notation

 function log(label,val){ document.body.append(label,String(val).replace(/,/g," - "),document.createElement("BR")); } const sortVersions = ( x, v = s => s.match(/[az]|\d+/g).map(c => c==~~c? String.fromCharCode(97 + c): c) ) => x.sort((a, b) => (a + b).match(/[az]/)? v(b) < v(a)? 1: -1: a.localeCompare(b, 0, {numeric: true})) let v=["1.90.1","1.090","1.0a","1.0.1","1.0.0a","1.0.0b","1.0.0.1","1.0a"]; log(' input: ',v); log('sorted: ',sortVersions(v)); log('no dups:',[...new Set(sortVersions(v))]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM