Previous Page
Next Page

Recipe 5.11. Implementing a Custom Sort

Problem

You want to sort an array using more complex logic than an alphabetical or numeric sort.

Solution

Use the sort( ) method and pass it a reference to a compare function.

Discussion

If you want complete control over sorting criteria, use the sort( ) method with a custom compare function (also called a sorter function). The sort( ) method repeatedly calls the compare function to reorder two elements of an array at a time. It sends the compare function two parameters (let's call them a and b). The compare function then determines which one should be ordered first by returning a positive number, a negative number, or 0, depending on how the elements are to be sorted. If the function returns a negative number, a is ordered before b. If the function returns 0, then the current order is preserved. If the function returns a positive number, a is ordered after b. The sort( ) method calls the compare function with every relevant combination of elements until the entire array has been properly ordered. Using a custom compare function is easier than it sounds. You don't need to concern yourself with the details of sorting the entire array; you simply specify the criteria for comparing any two elements.

One example of when you would want to use a custom sorter is when you need to sort a list of strings, but you need to process the strings somehow before sorting them. Say you are building a music program that needs to display a list of bands. If you just sorted the bands alphabetically, all the bands whose names began with "The" would appear together in the T section, which is probably not what you want. You can define a compare function that strips off "The" from the beginning of the name before comparing the bands. Here is the code to set up the array, perform a simple sort, and display the results:

var bands:Array = ["The Clash",
                   "The Who",
                   "Led Zeppelin",
                   "The Beatles",
                   "Aerosmith",
                   "Cream"];
bands.sort(  );
for(var i:int = 0; i < bands.length; i++) {
    trace(bands[i]);

    /* output:
       Aerosmith
       Cream
       Led Zeppelin
       The Beatles
       The Clash
       The Who
    */
}

To handle this, call the sort( ) method passing the bandNameSort compare function:

var bands:Array = ["The Clash",
                   "The Who",
                   "Led Zeppelin",
                   "The Beatles",
                   "Aerosmith",
                   "Cream"];
bands.sort(bandNameSort);
for(var i:int = 0; i < bands.length; i++) {
    trace(bands[i]);
    /* output:
       Aerosmith
       The Beatles
       The Clash
       Cream
       Led Zeppelin
       The Who
    */
}

function bandNameSort(band1:String, band2:String):int
{
    band1 = band1.toLowerCase(  );
    band2 = band2.toLowerCase(  );
    if(band1.substr(0, 4) == "the ") {
        band1 = band1.substr(4);
    }
    if(band2.substr(0, 4) == "the ") {
        band2 = band2.substr(4);
    }
    if(band1 < band2) {
        return -1;
    }
    else {
        return 1;
    }
}

The bandNameSort( ) function first converts both band names to lowercase, ensuring a case-insensitive sort. Then it checks to see if either band name begins with "The ". If so, it grabs the portion of the string from the fourth character to the end, which is everything after the word "The" plus the space.

Finally, it compares the two processed strings, returning -1 if the first string should go first, and 1 if the first string should go second. As you can see, the output is more in line with what you would expect.

There is no limit to how complex the compare function can be. If you are sorting a list of objects, you can build in logic that reads multiple properties of each object, performs calculations on their data, compares them, and returns the results.

Realize that the compare function may be run hundreds or even thousands of times in a single sort of a large array, so be careful about making it too complex.



Previous Page
Next Page
Converted from CHM to HTML with chm2web Pro 2.85 (unicode)