0

I am trying to sort a javascript array which my contains any type of data let say, numbers, strings, dates, times etc. My piece of logic is working well for all data types except numbers. It is considering number as string.

For example, I have a array like as follow:

array = ["1","2","12","22","33","3"]

I am expecting that sorted array would be 1,2,3,12,22,33… but it is giving: 1,12,2,22,3,33…

Can anybody refine my code that must work for any type of data type.

Here is my piece of code for sorting:

function sortTable(a,b){
    if(sortMode=="A"){
    if(a[1]>b[1]) return 1;
        if(a[1]<b[1]) return -1;
    }
    else if( sortMode=="D"){
        if(a[1]>b[1]) return -1;
        if(a[1]<b[1]) return 1;
    }
    return 0;     
}
array.sort(sortTable);

Note: I cannot predict that which datatype of data will be in my array… so sorting function must be generic. Meaning, I cannot call different sort technique functions for different data types… Please make sure that sorting function should work for all data types.

Richard M
  • 14,244
  • 6
  • 52
  • 48
Rama Rao M
  • 2,961
  • 11
  • 44
  • 64
  • 2
    You cannot create a sorting function that works with **all** datatypes just as like that. You'd have to make it accept a flag that defines how the values should be sorted (e.g. numerically, lexicographically) and maybe a converter function. That's more than just refining code... if you simply want to have the strings sorted numerically, convert the strings to numbers, which is explained here: http://stackoverflow.com/questions/1133770/how-do-i-convert-a-string-into-an-integer-in-javascript – Felix Kling Aug 17 '12 at 11:26
  • I can parse my string to integer..but what if my array is like this{"India","China","Russia"}.Can we convert these strings to integer? Thanks.. – Rama Rao M Aug 17 '12 at 11:32
  • If the array contains multiple data types, do you know how the types should be sorted? That is, should dates come before strings, numbers before dates, etc? – jackwanders Aug 17 '12 at 11:35
  • 1
    So your array can be `["1", "12", "2", "India", "China"]`? What do you expect it to look like after sorting? – pimvdb Aug 17 '12 at 11:36
  • @jackwanders No, Array does not contain different datatypes. It contais values of only one datatype. But that datatype may varies to array from array... My goal to write a function which can work for any array... – Rama Rao M Aug 17 '12 at 11:38
  • 1
    @RamaRaoM you could write a sort function that checks the types of the values being sorted, but that seems unnecessarily clunky, and even if you do that, how would you know that in some cases, your strings need to be coerced into numbers? – jackwanders Aug 17 '12 at 13:00

3 Answers3

1

The reason you are not getting the output you expect is that when both operands are of string type then an alphabetical comparison is made between them. They are not automatically converted to numbers.

"2" > "12" // result is true

If one of the operands is a number though the comparison operator will convert the other operand from a string to a number.

"2" > 12 // result is false

One other thing to point out is that, in the case of an array of numbers, you are attempting to access an array element at index 1.

if(a[1]>b[1]) return 1;

This should be:

if( a > b ) return 1;

I would handle each datatype separately rather than writing such a generic function.

Bruno
  • 5,772
  • 1
  • 26
  • 43
1

I wrote a couple regex conditions that check for certain data structures. (You could always just make a large switch statement that branches off based upon what 'typeof(a)' or 'typeof(b)' is.) These checks determine if the values inside a string should be interpreted as something other than strings.

function sortVals(a,b){
    //other code here  
    var aT=a+"", bT=b+"";    //a and b as strings
    if(!aT.match(/[^0-9]/) && !bT.match(/[^0-9]/)){//no non-numbers were found
        a = parseInt(aT, 10);
        b = parseInt(bT, 10);
        if(a!=b)
            return a<b?1:-1;    //returns 1 if a<b; -1 if a>b
    }else if(!aT.match(/[^0-9\.]|\..*\./) && !bT.match(/[^0-9\.]|\..*\./)){//only valid floats were found
        a = parseFloat(aT);
        b = parseFloat(bT);
        if(a!=b)
            return a<b?1:-1;
    }
}

I don't know if this is part of what you want, but if you want a sort function for any datatype, you'll need to put some work into it. Good luck!

cNovak
  • 94
  • 1
  • 9
1

As mentioned already, you 'd need to identify the data types. But heres one, that you can use for string/integers.

var sortMethod = function(x,y){
    var a = x|0 , 
        b = y|0; 
    return (a>b) ? 1 : -1;
});

var x = ["1", "34" , "3" , "12"].sort(sortMethod);
var y = [3,52,123,1].sort(sortMethod); 
sbr
  • 4,735
  • 5
  • 43
  • 49