SlightlyLoony
Tera Contributor
Options
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
07-14-2010
05:36 AM
Have you ever had trouble sorting stuff into the "right" order? JavaScript (and most other languages), by default, sorts numbers into numeric order and everything else into lexicographical (i.e., alphabetical) order. Often this is exactly what you need, but sometimes it's deeply wrong. For example, consider this list of IP addresses:
Lexicographical Order | Correct Order |
10.0.1.222 | 10.0.1.32 |
10.0.1.32 | 10.0.1.222 |
10.0.10.43 | 10.0.2.43 |
10.0.14.21 | 10.0.2.83 |
10.0.2.43 | 10.0.10.43 |
10.0.2.83 | 10.0.14.21 |
How can you persuade/coerce the %&^#$^@ computer to sort this correctly?
This little snippet sorts our test data into lexicographical order — what we don't want:
var ips = ['10.0.1.32','10.0.1.222','10.0.2.43','10.0.10.43','10.0.2.83','10.0.14.21'];
ips.sort();
gs.log(ips);
The trick to getting the order you want is to use a custom comparator. In JavaScript you do this by supplying a comparator function as a parameter to the sort method, as shown below. The sort method will then use this comparator to determine the sort order:
var ips = ['10.0.1.32','10.0.1.222','10.0.2.43','10.0.10.43','10.0.2.83','10.0.14.21'];
ips.sort(compareIPs);
gs.log(ips);
function compareIPs(a, b) {
var aa = getIPArray(a);
var ba = getIPArray(b);
for (var i = 0; i < aa.length; i++) {
var c = aa - ba;
if (c != 0)
return c;
}
return 0;
}
function getIPArray(x) {
var result = [];
var parts = x.split('.');
for (var i = 0; i < parts.length; i++)
result.push(parts - 0);
return result;
}
The comparator function (in our case, compareIPs) accepts two parameters a and b, which are to be compared. The comparator's job is to return zero if the two parameters are equal, some number greater than zero if a is greater than b, or some number less than zero if a is less than b.
The example given first converts each IP address string into an array of four numbers, then compares each of those number in a and b until it figures out which one is bigger. For instance, if the comparator was called with '10.0.1.23' and '10.0.10.43', it would first convert those strings to the arrays [10,0,1,23] and [10,0,10,43]. Then it would compare 10 and 10 (they're equal, so we keep going), 0 and 0 (again, they're equal, so we keep going), and finally 1 and 10 — since 1 is less than 10, it would return a negative number to show that a is less than b.
It may not be obvious until you try this a few times, but with a comparator you can implement any sort order at all. Furthermore, you can use custom comparators to sort arbitrary JavaScript objects, not just strings or numbers…
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.