javascriptarraysnatsort

Sorting alphanumeric array with java-script


I have a alphanumeric array -

var a1 =["3800tl-24G-2XG-PoEP", "3500", "stack-TA", "2620-48-PoEP", "2120", "3800tl-24G-2XG-PoEP"];

I tried sorting this array using natsort which gives me the correct output -

`Array ( [4] => 2120 [3] => 2620-48-PoEP [1] => 3500 [0] => 3800tl-24G-2XG-PoEP [5] => 3800tl-24G-2XG-PoEP [2] => stack-TA )`

I tried doing the same with javascript -

var a1 =["3800tl-24G-2XG-PoEP", "3500", "stack-TA", "2620-48-PoEP", "2120", "3800tl-24G-2XG-PoEP"];

    var a2 = a1.sort(function(a,b){
        var charPart = [a.substring(0,1), b.substring(0,1)],
            numPart = [a.substring(1)*1, b.substring(1)*1];

        if(charPart[0] < charPart[1]) return -1;
        else if(charPart[0] > charPart[1]) return 1;
        else{ //(charPart[0] == charPart[1]){
            if(numPart[0] < numPart[1]) return -1;
            else if(numPart[0] > numPart[1]) return 1;
            return 0;
        }
    });
    $('#r').html(a2.toString())

which gives me the output - 2620-48-PoEP,2120,3800tl-24G-2XG-PoEP,3500,3800tl-24G-2XG-PoEP,stack-TA.

Why the javascript code is not taking 2120 as the 1st element. What is wrong with the javascript code ?


Solution

  • Replace this line...

    [a.substring(1)*1, b.substring(1)*1]
    

    ... with ...

    [parseInt(a.substring(1), 10), parseInt(b.substring(1), 10)]
    

    ... and it will work (demo), though the sorting function still won't be as universal as possible.

    Explanation: a.substr(1)*1 (better written as just +a.substr(1), btw) casts that substring into Number type. In theory, that should give you a real number. In JS practice, however, it'll fail (giving NaN) if the rest of the string is not a complete representation of a number, having nothing except but that number.

    For example, for 2620-48-PoEP line, '620-48-PoEP' is cast to Number. Now JS cannot interpret it as 620 - it'll be too bold for it, as there are some other meaningful (=non-whitespace) characters there. So instead of giving you 620, it gives you NaN.

    Now, any comparison between NaN and NaN is false (expect !=) - and that'll essentially make your sorting function gone haywire.


    As a sidenote, array.sort updates the object in-place - you don't need to use another reference to it (a2 variable), you can work with a1.