Sort mixed alpha/numeric array
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; }}console.log(["A1", "A10", "A11", "A12", "A2", "A3", "A4", "B10", "B2", "F1", "F12", "F3"].sort(sortAlphaNum))
const sortAlphaNum = (a, b) => a.localeCompare(b, 'en', { numeric: true })
Usage:
const sortAlphaNum = (a, b) => a.localeCompare(b, 'en', { numeric: true })console.log(['A1', 'A10', 'A11', 'A12', 'A2', 'A3', 'A4', 'B10', 'B2', 'F1', 'F12', 'F3'].sort(sortAlphaNum))
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.
I had a similar situation, but, had a mix of alphanumeric & numeric and needed to sort all numeric first followed by alphanumeric, so:
A1015A92B3A2
needed to become:
125A2A9A10B3
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);