1

Here is my JavaScript code to sort data in an alphanumeric way:

var reA = /[^a-zA-Z]/g;
var reN = /[^0-9]/g;
function sortAlphaNum(a,b) {
    var aA = a.replace(reA, "");
    var bA = b.replace(reA, "");
    if(aA === bA) {
        var aN = parseInt(a.replace(reN, ""), 10);
        var bN = parseInt(b.replace(reN, ""), 10);
        return aN === bN ? 0 : aN > bN ? 1 : -1;
    } else {
        return aA > bA ? 1 : -1;
    }
}

my input data:

["ap1", "ap4", "ap12","4ggh2","7ggh9","9tggfg2","4gghdd2","4gghfg2"]

after sorting it should be like :

4ggh2,4hghdd2,4kghfg2,7ggh9,9tggfg2,ap1,ap4,ap12 

which is not happening could you please help me out in this.

function sortAlphaNum(a, b) { 
    var x = a.split("/"); 
    var y = b.split("/"); 
    x = x[x.length-1].replace(/\\\s/g," ").split(/(\d )/); 
    y = y[y.length-1].replace(/\\\s/g," ").split(/(\d )/);  
    for (var i in x) { 
        if (x[i] && !y[i] || isFinite(x[i]) && !isFinite(y[i])) { 
            return -1; 
        } else if (!x[i] && y[i] || !isFinite(y[i]) && isFinite(y[i])) { 
            return 1; 
        } else if (!isFinite(x[i]) && !isFinite(y[i])) { 
            x[i] = x[i].toLowerCase(); 
            y[i] = y[i].toLowerCase(); 
            if (x[i] < y[i]) return -1; 
            if (x[i] > y[i]) return 1; 
        } else { 
            x[i] = parseFloat(x[i]); 
            y[i] = parseFloat(y[i]); 
            if (x[i] < y[i]) return -1; 
            if (x[i] > y[i]) return 1; 
        } 
    } 
    return 0; 
}
alert(["ap1", "ap4", "ap12","4ggh2","7ggh9","9tggfg2","4hghdd2","4kghfg2"].sort(sortAlphaNum));
  • var input = ["ap1", "ap4", "ap12","4ggh2","7ggh9","9tggfg2","4gghdd2","4gghfg2"] – user2310261 Jun 05 '13 at 11:41
  • out put should be like : 4ggh2,4hghdd2,4kghfg2,7ggh9,9tggfg2,ap1,ap4,ap12 – user2310261 Jun 05 '13 at 11:42
  • You didn't show how you sort your data. By the way, `input = input.sort()` should be sufficient. What's somehow very strange: Your example output has different entries than your input. – Zeta Jun 05 '13 at 11:42
  • @Zeta - The `sort` function modifies the original array. Just `input.sort()` would suffice. – Aadit M Shah Jun 05 '13 at 11:44
  • 1
    So you've just copied code from http://stackoverflow.com/questions/4340227/sort-mixed-alpha-numeric-array ? – boxed Jun 05 '13 at 11:49
  • The code you have now only works for a more limited pattern (leading letters, then a single number). – Thilo Jun 05 '13 at 11:51

2 Answers2

1

This example adds a method to the Array prototype,

but it can be written as a standalone function with the array to be sorted passed as an argument if you prefer.

Array.prototype.naturalSort= function(index){
    var T= this, L= T.length, i, who, next, 
    isi= typeof index== 'number', 
    rx=/(\.\d+)|(\d+(\.\d+)?)|([^\d.]+)|(\.\D+)|(\.$)/g;
    function nSort(aa, bb){
        var a= aa[0], b= bb[0], a1, b1, i= 0, n, L= a.length;
        while(i<L){
            if(!b[i]) return 1;
            a1= a[i];
            b1= b[i++];
            if(a1!== b1){
                n= a1-b1;
                if(!isNaN(n)) return n;
                return a1>b1? 1:-1;
            }
        }
        return b[i]? -1:0;
    }
    for(i= 0; i<L; i++){
        who= T[i];
        next= isi? T[i][index] || '':who;
        T[i]= [String(next).toLowerCase().match(rx), who];
    }
    T.sort(nSort);
    for(i= 0; i<L; i++){
        T[i]= T[i][1];
    }
    return this;
}
var A= ["ap1","ap4","ap12","4ggh2","7ggh9","9tggfg2","4gghdd2","4gghfg2"];

A.naturalSort();

// returned value: (Array) // 4ggh2,4gghdd2,4gghfg2,7ggh9,9tggfg2,ap1,ap4,ap12

  1. The example first goes through the entire array and sets each item to a new two-item array- the first item of the new array is a matched array of numbers and strings, the second is the original value.

In your example, array[5]= '9tggfg2', becomes array[5]= [['9', 'tggfg', '2'], '9tggfg2']]. That way the reg exp, match and and toLowerCase operations are only done once for each item, rather than every time the sort compares two items.

  1. After the array is prepped, the sort function is applied, which compares items alphabetically if they are both alpha-strings and numerically if they are both number-strings. Number-strings sort before(are less-than) alpha-strings.

  2. After the sort, the array is again processed, this time to reset each item to its original value.

You can use the same logic without the pre-sort and post-sort parts, but if you have more than three items it takes longer:

function natSort(as, bs){
    var a, b, a1, b1, i= 0, n, L, 
    rx=/(\.\d+)|(\d+(\.\d+)?)|([^\d.]+)|(\.\D+)|(\.$)/g;
    a= String(as).toLowerCase().match(rx);
    b= String(bs).toLowerCase().match(rx);
    if(as=== bs) return 0;
    L= a.length;
    while(i<L){
        if(!b[i]) return 1;
        a1= a[i], 
        b1= b[i++];
        if(a1!== b1){
            n= a1-b1;
            if(!isNaN(n)) return n;
            return a1>b1? 1:-1;
        }
    }
    return b[i]? -1:0;
}
   ["ap1", "ap4", "ap12", "4ggh2", "7ggh9", 
"9tggfg2", "4gghdd2", "4gghfg2"].sort(natSort);

returned value: (Array) 4ggh2,4gghdd2,4gghfg2,7ggh9,9tggfg2,ap1,ap4,ap12

kennebec
  • 102,654
  • 32
  • 106
  • 127
0

Try:

var input = ["ap1", "ap4", "ap12","4ggh2","7ggh9","9tggfg2","4gghdd2","4gghfg2"];
input.sort();

See the demo: http://jsfiddle.net/xmkVr/

Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299