I would like to sort an array of strings (in javascript) so that groups of numbers inside strings are compared as integers, not strings. I'm not worried about signed or floating point numbers.
for example, the result should be ["a1b3","a9b2","a10b2","a10b11"] not ["a1b3","a10b11","a10b2","a9b2"]
The easiest way to do this is to split each line into borders around groups of numbers. Is there a pattern that I can pass to String.split to split at the borders of characters without deleting any characters?
"abc11def22ghi".split(/?/) = ["abc","11","def","22","ghi"];
Or is there another way to compare strings that are not related to their splitting, perhaps filling all groups of digits with leading zeros so that they are the same length?
"aa1bb" => "aa00000001bb", "aa10bb" => "aa00000010bb"
I work with arbitrary strings, not strings that have a specific arrangement of groups of numbers.
Edit:
I like the /(\d+)/ one liner from Gaby to split the array. How compatible is this compatibility?
Solutions that parse strings once in a way that can be used to restore originals are much more efficient than this comparison function. None of the answers handles some lines, starting with numbers, while others do not, but that would be easy enough to fix and not be obvious in the original question.
["a100","a20","a3","a3b","a3b100","a3b20","a3b3","!!","~~","9","10","9.5"].sort( function ( inA , inB ) { var result = 0; var a , b , pattern = /(\d+)/; var as = inA.split( pattern ); var bs = inB.split( pattern ); var index , count = as.length; if ( ( '' === as[0] ) === ( '' === bs[0] ) ) { if ( count > bs.length ) count = bs.length; for ( index = 0 ; index < count && 0 === result ; ++index ) { a = as[index]; b = bs[index]; if ( index & 1 ) { result = a - b; } else { result = !( a < b ) ? ( a > b ) ? 1 : 0 : -1; } } if ( 0 === result ) result = as.length - bs.length; } else { result = !( inA < inB ) ? ( inA > inB ) ? 1 : 0 : -1; } return result; } ).toString();
result: "!!,9,9.5,10,a3,a3b,a3b3,a3b20,a3b100,a20,a100,~~"