How to perform case-insensitive sorting array of string in JavaScript?
JavascriptSortingCase InsensitiveJavascript Problem Overview
I have an array of strings I need to sort in JavaScript, but in a case-insensitive way. How to perform this?
Javascript Solutions
Solution 1 - Javascript
In (almost :) a one-liner
["Foo", "bar"].sort(function (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
Which results in
[ 'bar', 'Foo' ]
While
["Foo", "bar"].sort();
results in
[ 'Foo', 'bar' ]
Solution 2 - Javascript
It is time to revisit this old question.
You should not use solutions relying on toLowerCase
. They are inefficient and simply don't work in some languages (Turkish for instance). Prefer this:
['Foo', 'bar'].sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'}))
Check the documentation for browser compatibility and all there is to know about the sensitivity
option.
Solution 3 - Javascript
myArray.sort(
function(a, b) {
if (a.toLowerCase() < b.toLowerCase()) return -1;
if (a.toLowerCase() > b.toLowerCase()) return 1;
return 0;
}
);
EDIT: Please note that I originally wrote this to illustrate the technique rather than having performance in mind. Please also refer to answer @Ivan Krechetov for a more compact solution.
Solution 4 - Javascript
arr.sort(function(a,b) {
a = a.toLowerCase();
b = b.toLowerCase();
if (a == b) return 0;
if (a > b) return 1;
return -1;
});
Solution 5 - Javascript
ES6 version:
["Foo", "bar"].sort((a, b) => a.localeCompare(b, 'en', { sensitivity: 'base' }))
Solution 6 - Javascript
You can also use the new Intl.Collator().compare
, per MDN it's more efficient when sorting arrays. The downside is that it's not supported by older browsers. MDN states that it's not supported at all in Safari. Need to verify it, since it states that Intl.Collator
is supported.
> 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
["Foo", "bar"].sort(Intl.Collator().compare); //["bar", "Foo"]
Solution 7 - Javascript
If you want to guarantee the same order regardless of the order of elements in the input array, here is a stable sorting:
myArray.sort(function(a, b) {
/* Storing case insensitive comparison */
var comparison = a.toLowerCase().localeCompare(b.toLowerCase());
/* If strings are equal in case insensitive comparison */
if (comparison === 0) {
/* Return case sensitive comparison instead */
return a.localeCompare(b);
}
/* Otherwise return result */
return comparison;
});
Solution 8 - Javascript
Normalize the case in the .sort()
with .toLowerCase()
.
Solution 9 - Javascript
You can also use the Elvis operator:
arr = ['Bob', 'charley', 'fudge', 'Fudge', 'biscuit'];
arr.sort(function(s1, s2){
var l=s1.toLowerCase(), m=s2.toLowerCase();
return l===m?0:l>m?1:-1;
});
console.log(arr);
Gives:
biscuit,Bob,charley,fudge,Fudge
The localeCompare method is probably fine though...
Note: The Elvis operator is a short form 'ternary operator' for if then else, usually with assignment.
If you look at the ?: sideways, it looks like Elvis...
i.e. instead of:
if (y) {
x = 1;
} else {
x = 2;
}
you can use:
x = y?1:2;
i.e. when y is true, then return 1 (for assignment to x), otherwise return 2 (for assignment to x).
Solution 10 - Javascript
The other answers assume that the array contains strings. My method is better, because it will work even if the array contains null, undefined, or other non-strings.
var notdefined;
var myarray = ['a', 'c', null, notdefined, 'nulk', 'BYE', 'nulm'];
myarray.sort(ignoreCase);
alert(JSON.stringify(myarray)); // show the result
function ignoreCase(a,b) {
return (''+a).toUpperCase() < (''+b).toUpperCase() ? -1 : 1;
}
The null
will be sorted between 'nulk' and 'nulm'. But the undefined
will be always sorted last.
Solution 11 - Javascript
In support of the accepted answer I would like to add that the function below seems to change the values in the original array to be sorted so that not only will it sort lower case but upper case values will also be changed to lower case. This is a problem for me because even though I wish to see Mary next to mary, I do not wish that the case of the first value Mary be changed to lower case.
myArray.sort(
function(a, b) {
if (a.toLowerCase() < b.toLowerCase()) return -1;
if (a.toLowerCase() > b.toLowerCase()) return 1;
return 0;
}
);
In my experiments, the following function from the accepted answer sorts correctly but does not change the values.
["Foo", "bar"].sort(function (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
Solution 12 - Javascript
arr.sort(function(a,b) {
a = a.toLowerCase();
b = b.toLowerCase();
if( a == b) return 0;
if( a > b) return 1;
return -1;
});
In above function, if we just compare when lower case two value a and b, we will not have the pretty result.
Example, if array is [A, a, B, b, c, C, D, d, e, E] and we use the above function, we have exactly that array. It's not changed anything.
To have the result is [A, a, B, b, C, c, D, d, E, e], we should compare again when two lower case value is equal:
function caseInsensitiveComparator(valueA, valueB) {
var valueALowerCase = valueA.toLowerCase();
var valueBLowerCase = valueB.toLowerCase();
if (valueALowerCase < valueBLowerCase) {
return -1;
} else if (valueALowerCase > valueBLowerCase) {
return 1;
} else { //valueALowerCase === valueBLowerCase
if (valueA < valueB) {
return -1;
} else if (valueA > valueB) {
return 1;
} else {
return 0;
}
}
}
Solution 13 - Javascript
This may help if you have struggled to understand:
var array = ["sort", "Me", "alphabetically", "But", "Ignore", "case"];
console.log('Unordered array ---', array, '------------');
array.sort(function(a,b) {
a = a.toLowerCase();
b = b.toLowerCase();
console.log("Compare '" + a + "' and '" + b + "'");
if( a == b) {
console.log('Comparison result, 0 --- leave as is ');
return 0;
}
if( a > b) {
console.log('Comparison result, 1 --- move '+b+' to before '+a+' ');
return 1;
}
console.log('Comparison result, -1 --- move '+a+' to before '+b+' ');
return -1;
});
console.log('Ordered array ---', array, '------------');
// return logic
/***
If compareFunction(a, b) is less than 0, sort a to a lower index than b, i.e. a comes first.
If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.
If compareFunction(a, b) is greater than 0, sort b to a lower index than a.
***/
Solution 14 - Javascript
I wrapped the top answer in a polyfill so I can call .sortIgnoreCase() on string arrays
// Array.sortIgnoreCase() polyfill
if (!Array.prototype.sortIgnoreCase) {
Array.prototype.sortIgnoreCase = function () {
return this.sort(function (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
};
}
Solution 15 - Javascript
Wrap your strings in / /i
. This is an easy way to use regex to ignore casing