Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I have a mixed array that I need to sort by alphabet and then by digit

[A1, A10, A11, A12, A2, A3, A4, B10, B2, F1, F12, F3]

How do I sort it to be:

[A1, A2, A3, A4, A10, A11, A12, B2, B10, F1, F3, F12]

I have tried

arr.sort(function(a,b) {return a - b});

but that only sorts it alphabetically. Can this be done with either straight JavaScript or jQuery?

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; console.log( ["A1", "A10", "A11", "A12", "A2", "A3", "A4", "B10", "B2", "F1", "F12", "F3"].sort(sortAlphaNum) So catching up a little late...but you don't need the else block since the first if will return if aA === bA – phatskat Jan 20, 2014 at 16:40 This is a good answer but it very badly needs comments. It took me awhile to read this and for it to make sense. – zfrisch May 30, 2017 at 21:16 @epascarello I really appreciated it when I found it - it's just a little perplexing when you first view it. It's succinct, but not thematically named, and if you're not familiar with regular expressions, ternary, or general sorting it's a bit of a leap to understand. Alphanumeric sorting is a pretty common question, and the ramp up to asking it doesn't require more than a cursory knowledge of arrays, so assuming more than that is going to get people asking for commentary. It's a good answer and your prerogative, but a description would likely make it easier to digest for everyone interested. – zfrisch Jun 17, 2019 at 19:48

Gives:

["A1", "A2", "A3", "A4", "A10", "A11", "A12", "B2", "B10", "F1", "F3", "F12"]

You may have to change the 'en' argument to your locale or determine programatically but this works for english strings.

localeCompare is supported by IE11, Chrome, Firefox, Edge and Safari 10.

This should be the accepted answer IMO. Small nit: The first line contains a trailing backtick after { numeric: true }) – w3dot0 Mar 1, 2021 at 15:11

I had a similar situation, but, had a mix of alphanumeric & numeric and needed to sort all numeric first followed by alphanumeric, so:

needed to become:

I was able to use the supplied algorithm and hack a bit more onto it to accomplish this:

var reA = /[^a-zA-Z]/g;
var reN = /[^0-9]/g;
function sortAlphaNum(a,b) {
    var AInt = parseInt(a, 10);
    var BInt = parseInt(b, 10);
    if(isNaN(AInt) && isNaN(BInt)){
        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;
    }else if(isNaN(AInt)){//A is not an Int
        return 1;//to make alphanumeric sort first return -1 here
    }else if(isNaN(BInt)){//B is not an Int
        return -1;//to make alphanumeric sort first return 1 here
    }else{
        return AInt > BInt ? 1 : -1;
var newlist = ["A1", 1, "A10", "A11", "A12", 5, 3, 10, 2, "A2", "A3", "A4", "B10", "B2", "F1", "F12", "F3"].sort(sortAlphaNum);
                ["a25b", "ab", "a37b"] will produces [ "a25b", "ab", "a37b" ] instead of [ "a25b", "a37b", "ab" ].
– 林果皞
                Dec 21, 2017 at 20:07
let arr = ["A1", "A10", "A11", "A12", "A2", "A3", "A4", "B10", "B2", "F1", "F12", "F3"]
let op = arr.sort(new Intl.Collator('en',{numeric:true, sensitivity:'accent'}).compare)
console.log(op)
I tried benchmarking this in Node.js and it is hugely faster than the localeCompare answers. I tested both over 1000 iterations and the localeCompare took 3.159 seconds, this Intl.Collator took just 200.178ms under the same conditions, pretty impressive. – PurplProto Feb 24, 2021 at 16:43

A simple way to do this is use the localeCompare() method of JavaScript https://www.w3schools.com/jsref/jsref_localecompare.asp

Example:

export const sortAlphaNumeric = (a, b) => {
    // convert to strings and force lowercase
    a = typeof a === 'string' ? a.toLowerCase() : a.toString();
    b = typeof b === 'string' ? b.toLowerCase() : b.toString();
    return a.localeCompare(b);

Expected behavior:

1000X Radonius Maximus
10X Radonius
200X Radonius
20X Radonius
20X Radonius Prime
30X Radonius
40X Radonius
Allegia 50 Clasteron
Allegia 500 Clasteron
Allegia 50B Clasteron
Allegia 51 Clasteron
Allegia 6R Clasteron
Alpha 100
Alpha 2
Alpha 200
Alpha 2A
Alpha 2A-8000
Alpha 2A-900
Callisto Morphamax
Callisto Morphamax 500
Callisto Morphamax 5000
Callisto Morphamax 600
Callisto Morphamax 6000 SE
Callisto Morphamax 6000 SE2
Callisto Morphamax 700
Callisto Morphamax 7000
Xiph Xlater 10000
Xiph Xlater 2000
Xiph Xlater 300
Xiph Xlater 40
Xiph Xlater 5
Xiph Xlater 50
Xiph Xlater 500
Xiph Xlater 5000
Xiph Xlater 58
var a1 =["A1", "A10", "A11", "A12", "A2", "A3", "A4", "B10", "B2", "F1", "F12", "F3"];
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())

http://jsfiddle.net/8fRsD/

function parseItem (item) {
  const [, stringPart = '', numberPart = 0] = /(^[a-zA-Z]*)(\d*)$/.exec(item) || [];
  return [stringPart, numberPart];
function sort (array) {
  return array.sort((a, b) => {
    const [stringA, numberA] = parseItem(a);
    const [stringB, numberB] = parseItem(b);
    const comparison = stringA.localeCompare(stringB);
    return comparison === 0 ? Number(numberA) - Number(numberB) : comparison;
console.log(sort(['A1', 'A10', 'A11', 'A12', 'A2', 'A3', 'A4', 'B10', 'B2', 'F1', 'F12', 'F3']))
console.log(sort(['a25b', 'ab', 'a37b']))

I recently worked on a project involving inventory and bin locations. The data needed to be sorted by bin location and was in an array of objects.

For anyone wanting to handle the sorting of this type of data, and your data is in an array of objects, you can do this:

const myArray = [
    { location: 'B3',   item: 'A', quantity: 25 },
    { location: 'A11',  item: 'B', quantity: 5 },
    { location: 'A6',   item: 'C', quantity: 245 },
    { location: 'A9',   item: 'D', quantity: 15 },
    { location: 'B1',   item: 'E', quantity: 65 },
    { location: 'SHOP', item: 'F', quantity: 42 },
    { location: 'A7',   item: 'G', quantity: 57 },
    { location: 'A3',   item: 'H', quantity: 324 },
    { location: 'B5',   item: 'I', quantity: 4 },
    { location: 'A5',   item: 'J', quantity: 58 },
    { location: 'B2',   item: 'K', quantity: 45 },
    { location: 'A10',  item: 'L', quantity: 29 },
    { location: 'A4',   item: 'M', quantity: 11 },
    { location: 'B4',   item: 'N', quantity: 47 },
    { location: 'A1',   item: 'O', quantity: 55 },
    { location: 'A8',   item: 'P', quantity: 842 },
    { location: 'A2',   item: 'Q', quantity: 67 }
const sortArray = (sourceArray) => {
    const sortByLocation = (a, b) => a.location.localeCompare(b.location, 'en', { numeric: true });
    //Notice that I specify location here ^^       and here        ^^ using dot notation
    return sourceArray.sort(sortByLocation);
console.log('unsorted:', myArray);
console.log('sorted by location:', sortArray(myArray));

You can easily sort by any of the other keys as well. In this case, item or quantity using dot notation as shown in the snippet.

Javascript Array Sort function takes 1 optional argument that compare function. You can set this compare function as your requirements.

arr.sort([compareFunction])

compareFunction(Optional). Specifies a function that defines the sort order. If omitted, the array is sorted according to each character's Unicode code point value, according to the string conversion of each element. - MDN

Adding to the accepted answer from epascarello, since I cannot comment on it. I'm still a noob here. When one of the strinngs doesn't have a number the original answer will not work. For example A and A10 will not be sorted in that order. Hence you might wamnt to jump back to normal sort in that case.

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);
      if(isNaN(bN) || isNaN(bN)){
        return  a > b ? 1 : -1;
      return aN === bN ? 0 : aN > bN ? 1 : -1;
    } else {
     return aA > bA ? 1 : -1;
 ["A1", "A10", "A11", "A12", "A2", "A3", "A4", "B10", "B2", "F1", "F12","F3"].sort(sortAlphaNum);`

Only problem with the above given solution was that the logic failed when numeric data was same & alphabets varied e.g. 28AB, 28PQR, 28HBC. Here is the modified code.

var reA = /[^a-zA-Z]/g;
    var reN = /[^0-9]/g;
    var AInt = parseInt(a, 10);
    var BInt = parseInt(b, 10);
    if(isNaN(AInt) && isNaN(BInt)){
        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);
            alert("in if "+aN+" : "+bN);
            return aN === bN ? 0 : aN > bN ? 1 : -1;
        } else {
            return aA > bA ? 1 : -1;
    }else if(isNaN(AInt)){//A is not an Int
        return 1;//to make alphanumeric sort first return 1 here
    }else if(isNaN(BInt)){//B is not an Int
        return -1;//to make alphanumeric sort first return -1 here
    }else if(AInt == BInt) {
        var aA = a.replace(reA, "");
        var bA = b.replace(reA, "");
        return aA > bA ? 1 : -1;
    else {
        return AInt > BInt ? 1 : -1;

Here is an ES6 Typescript upgrade to this answer.

export function SortAlphaNum(a: string, b: string) {
    const reA = /[^a-zA-Z]/g;
    const reN = /[^0-9]/g;
    const aA = a.replace(reA, "");
    const bA = b.replace(reA, "");
    if (aA === bA) {
      const aN = parseInt(a.replace(reN, ""), 10);
      const bN = parseInt(b.replace(reN, ""), 10);
      return aN === bN ? 0 : aN > bN ? 1 : -1;
    } else {
      return aA > bA ? 1 : -1;
    //return b.text - a.text;
    var AInt = parseInt(a.text, 10);
    var BInt = parseInt(b.text, 10);
    if ($.isNumeric(a.text) == false && $.isNumeric(b.text) == false) {
        var aA = a.text
        var bA = b.text;
        return aA > bA ? 1 : -1;
    } else if ($.isNumeric(a.text) == false) {  // A is not an Int
        return 1;    // to make alphanumeric sort first return -1 here
    } else if ($.isNumeric(b.text) == false) {  // B is not an Int
        return -1;   // to make alphanumeric sort first return 1 here
    } else {
        return AInt < BInt ? 1 : -1;

This works fine for a well mixed array.:)

Thank you.

let ax = [], bx = []; a.replace(/(\d+)|(\D+)/g, function (_, $1, $2) { ax.push([$1 || Infinity, $2 || '']) }); b.replace(/(\d+)|(\D+)/g, function (_, $1, $2) { bx.push([$1 || Infinity, $2 || '']) }); while (ax.length && bx.length) { let an = ax.shift(); let bn = bx.shift(); let nn = (an[0] - bn[0]) || an[1].localeCompare(bn[1]); if (nn) { return nn; return ax.length - bx.length; array.sort((a, b) => { let v0 = a.replace(reg, v => v.padStart(10, '0')); let v1 = b.replace(reg, v => v.padStart(10, '0')); return v0.localeCompare(v1);

Here's a version (based on the answer of @SunnyPenguin & @Code Maniac) that is in TypeScript as a library function. Variable names updated & comments added for clarity.

// Sorts strings with numbers by keeping the numbers in ascending order
export const sortAlphaNum: Function = (a: string, b: string, locale: string): number => {
  const letters: RegExp = /[^a-zA-Z]/g;
  const lettersOfA: string = a.replace(letters, '');
  const lettersOfB: string = b.replace(letters, '');
  if (lettersOfA === lettersOfB) {
    const numbers: RegExp = /[^0-9]/g;
    const numbersOfA: number = parseInt(a.replace(numbers, ''), 10);
    const numbersOfB: number = parseInt(b.replace(numbers, ''), 10);
    if (isNaN(numbersOfA) || isNaN(numbersOfB)) {
      // One is not a number - comparing letters only
      return new Intl.Collator(locale, { sensitivity: 'accent' }).compare(a, b);
    // Both have numbers - compare the numerical parts
    return numbersOfA === numbersOfB ? 0 : numbersOfA > numbersOfB ? 1 : -1;
  } else {
    // Letter parts are different - comparing letters only
    return new Intl.Collator(locale, { sensitivity: 'accent' }).compare(lettersOfA, lettersOfB);
    var smlla = a.toLowerCase();
    var smllb = b.toLowerCase();
    var result = smlla > smllb ? 1 : -1;
    return result;
                This is wrong. Try comparing A10 to A2. This will sort A10 before A2, but A2 should be sorted before A10.
– Uyghur Lives Matter
                Jul 14, 2015 at 0:53
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.