Wednesday, November 17, 2010

How to sort an Array of Strings ?

Recently I had the requirement to sort an Array, alphabetically. My first thoughts were, "pretty trivial with Array.prototype.sort(), ehh!".

As it turned out, it's not that trivial at all. First thing to mention here is, that the particular Array consisted out of Objects, which among other things, contained a string property.
The requirement was, to sort the Array based on this property.

Because of that, I couldn't ordinary call Array.sort(), I needed to pass in a custom sorting logic. So the first idea was just to call this:

// --
var arr = [{value: 'Foo'}, {value: 'Javascript'}, {value: 'MooTols'}, {value: 'Zebra'}, {value: 'Ape'}];

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

At first sight, this works pretty well. But what happens to this "operator based" comparison, if you have special characters, umlauts or numbers like '05' and '11' at the beginning of the strings? It will fail. That means the order will not be as you might expect it to be. For that reason, Javascript 1.2 introduced a String method called 'localeCompare(compareString)'.

From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/localeCompare

Description
Returns a number indicating whether a reference string comes before or after or is the same as the given string in sort order. Returns -1 if the string occurs earlier in a sort thancompareString, returns 1 if the string occurs afterwards in such a sort, and returns 0 if they occur at the same level.


So our sorting function should look like:

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

On the performance side, a quick measuring showed that the operator version is faster on Firefox & Safari. Chrome has a better performance with localeCompare. Don't forget that the former version brings wrong results, so you actually should always go with localeCompare.

http://jsperf.com/operator-vs-localecompage

See you next time!

- Andy

No comments:

Post a Comment