Voted Best Answer. You should be using the JavaScript array object's sort method. If you are going to sort strings that consist of letters and numbers you may need to pad some numbers with leading zeros so the numeric portion of the string is the same length for all members.
The sort() method sorts the elements of an array in place and returns the reference to the same array, now sorted. The default sort order is ascending, built upon converting the elements into strings, then comparing their sequences of UTF-16 code units values.
In computing, natural sort order (or natural sorting) is the ordering of strings in alphabetical order, except that multi-digit numbers are treated atomically, i.e., as if they were a single character.
This is now possible in modern browsers using localeCompare. By passing the numeric: true
option, it will smartly recognize numbers. You can do case-insensitive using sensitivity: 'base'
. Tested in Chrome, Firefox, and IE11.
Here's an example. It returns 1
, meaning 10 goes after 2:
'10'.localeCompare('2', undefined, {numeric: true, sensitivity: 'base'})
For performance when sorting large numbers of strings, the article says:
When comparing large numbers of strings, such as in sorting large arrays, it is better to create an Intl.Collator object and use the function provided by its compare property. Docs link
var collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'});
var myArray = ['1_Document', '11_Document', '2_Document'];
console.log(myArray.sort(collator.compare));
So you need a natural sort ?
If so, than maybe this script by Brian Huisman based on David koelle's work would be what you need.
It seems like Brian Huisman's solution is now directly hosted on David Koelle's blog:
If you have a array of objects you can do like this:
myArrayObjects = myArrayObjects.sort(function(a, b) {
return a.name.localeCompare(b.name, undefined, {
numeric: true,
sensitivity: 'base'
});
});
var myArrayObjects = [{
"id": 1,
"name": "1 example"
},
{
"id": 2,
"name": "100 example"
},
{
"id": 3,
"name": "12 example"
},
{
"id": 4,
"name": "5 example"
},
]
myArrayObjects = myArrayObjects.sort(function(a, b) {
return a.name.localeCompare(b.name, undefined, {
numeric: true,
sensitivity: 'base'
});
});
console.log(myArrayObjects);
To compare values you can use a comparing method-
function naturalSorter(as, bs){
var a, b, a1, b1, i= 0, n, L,
rx=/(\.\d+)|(\d+(\.\d+)?)|([^\d.]+)|(\.\D+)|(\.$)/g;
if(as=== bs) return 0;
a= as.toLowerCase().match(rx);
b= bs.toLowerCase().match(rx);
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;
}
But for speed in sorting an array, rig the array before sorting, so you only have to do lower case conversions and the regular expression once instead of in every step through the sort.
function naturalSort(ar, index){
var L= ar.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]!= undefined? -1: 0;
}
for(i= 0; i<L; i++){
who= ar[i];
next= isi? ar[i][index] || '': who;
ar[i]= [String(next).toLowerCase().match(rx), who];
}
ar.sort(nSort);
for(i= 0; i<L; i++){
ar[i]= ar[i][1];
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With