1

I need to alphabetize a list of software versions in Angular from latest to oldest (i.e. 1.10.3.e, 1.9.5.b, 1.7.3, 1.5.1.c). I have been using .sort() which sorts alphabetically but treats the values as a string resulting in any 1.10 version to be sorted after a 1.5 version as it looks at the 1 and 0 independently.I tried doing .sort((a, b) => b - a) and it completely randomized the list rather than sorting it. I have also tried using .slice('.') which does not seem to work.

Any ideas?

peinearydevelopment
  • 11,042
  • 5
  • 48
  • 76
Cole Henderson
  • 305
  • 4
  • 11
  • This is not really an angular question, any typescript/javascript solution will work. You can check this question: https://stackoverflow.com/questions/6832596/how-to-compare-software-version-number-using-js-only-number – LambdaCruiser Jan 03 '19 at 14:54

2 Answers2

1

This isn't an easy question to answer as there are a few variables to consider. Assuming that you will never have versions like 1.1, 1.a, then the following should do the trick.

var arr = ['1.10.3.e', '1.9.5.b', '1.7.3', '1.5.1.c', '1.5.1.a', '1.5.1.d', '1.10', '1.5']
          .map(a => a.split('.') // split by decimals
                     .map(i => Number.isNaN(parseInt(i, 10)) ? i : parseInt(i, 10))) // make numbers numbers, leave chars as strings
          .sort((a,b) => {
              // sort by multiple indexes and if one array is shorter, it's i item will be undefined
              var longerIndex = a.length > b.length ? a.length : b.length;
              for(var i = 0, l = longerIndex; i < l; i++) {
                if (a[i] > b[i] || b[i] === undefined) return 1;
                else if (a[i] < b[i] || a[i] === undefined) return -1;
              }

              return 0;
          })
          .map(a => a.join('.')) // join the version parts back into a single string
console.log(arr);
peinearydevelopment
  • 11,042
  • 5
  • 48
  • 76
1

Solution 1): temporary pad with '0':

(If a part of the version number could become more than 2 digits, padStart could be changed to 3, 4, ...)

var vers = [ '1.10.3.e', '1.9.5.b', '1.7.3', '1.5.1.c' ];
console.log( vers );

var temp = vers.map( function( s ){
    return s.split('.').map( function( n ){ return n.padStart(2,'0'); } ).join('.');
} )

temp.sort();

vers = temp.map( function( s ){
    return s.split('.').map( function( n ){ return n.replace(/^0+/, ''); } ).join('.');
} )

console.log( temp );
console.log( vers );

Solution 2): sort seperately by integers and strings.
I would call this the more elegant solution, even if it is a bit more complicated.
(Such an answer, with integers, has been given already)

kca
  • 4,856
  • 1
  • 20
  • 41
  • Worked like a charm. Some of my versions have the number 0 at the end so I replaced .padStart(2, '0') with .padStart(2. '!'). Thank you! – Cole Henderson Jan 03 '19 at 17:19