JSON.stringify()
will escape some characters (like double quote characters, backslash character or any control character) so those characters aren't likely to sort properly.
Also, since a space has a lower ascii code than a double quote, if your two arrays start with "abcd "
and "abcd"
, they won't sort properly in the JSON. "abcd "
should come after "abcd"
, but the space has a lower ascii value than the double quote so it will sort before. The same would be true for an exclamation point at the end of the value.
If, according to your comments you also want this to work for non-array members like numbers, a string comparison does not work for comparing two numbers with differing number of digits as 1000
is not less than 2
, but "1000"
is less than "2"
.
Also, I would suggest that you use .localeCompare()
for comparing two strings in your second algorithm as it already has the built-in positive, negative or zero result.
If all your values are strings or they sort properly via .toString()
, you could use .localeCompare()
like this:
data.sort(function(a, b) {
var comp, i;
for (i = 0; i < Math.min(a.length, b.length); i++) {
if ((comp = a[i].localeCompare(b[i])) !== 0) return comp;
}
return (a.length > b.length) - (a.length < b.length);
});
.localeCompare
also has options you can use for case sensitivity, for ignoring punctuation, for how to treat accented characters, and a few others.
Per your comment and per MDN, you can get better performance in the comparison with a Collator object (only available in some browsers). Per the doc (I've only tried this code once myself), it works like this:
var collater = new Intl.Collator();
data.sort(function(a, b) {
var comp, i;
for (i = 0; i < Math.min(a.length, b.length); i++) {
if ((comp = collater.compare(a[i], b[i])) !== 0) return comp;
}
return (a.length > b.length) - (a.length < b.length);
});
Presumably there must be some initialization or overhead that can be done just once this way. Perhaps they build direct lookup sort tables.
But browser support for the Collator object is sparse (IE 11, Chrome, no Firefox, no Safari) so unless you were using this in a browser add-on so the code was specific to only one browser, you'd have to branch on whether it was supported or not and have two implementations.
P.S. If you have any sizable number of outer array elements, thus calling the sort callback a lot of times, it would perform pretty horribly. You could at least make it so that it only does two JSON.stringify()
calls each time rather than four.