You want to sort an array in a way such that the basic sort( ) and sortOn( ) methods do not suffice. You want to sort an array in a case-insensitive manner, perform a numeric sort, or use another custom or multikey criterion.
Use the sort( ) method and pass it a reference to a compare function.
If you want complete control over sorting criteria, use the sort( ) method with a custom compare function (also called a sorter function). The compare function is called repeatedly by the sort( ) method to reorder two elements of the array at a time. The compare function receives two parameters (let's call them a and b), which it should compare to determine which one should be ordered first. Your custom compare function should return 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. Your compare function is called 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 do not need to concern yourself with the details of the sorting algorithm; you simply specify the criteria for comparing any two elements.
Here is a simple compare function that performs a case-insensitive sort:
function insensitiveSorter(a, b) { itemOne = a.toUpperCase( ); itemTwo = b.toUpperCase( ); if (itemOne > itemTwo) { return 1; } else if (itemOne < itemTwo) { return -1; } else { return 0 } }
Case-insensitive sorting is useful when you have an array of values with mixed cases, because Flash automatically sorts all uppercase letters before lowercase letters by default:
myArray = ["cardinal", "California", "camel", "Chicago"]; myArray.sort( ); trace(myArray); // Displays: California,Chicago,camel,cardinal
However, when you use the case-insensitive sort utilizing the custom sorter function as defined previously, Flash sorts the values in alphabetical order regardless of case:
myArray = ["cardinal", "California", "camel", "Chicago"]; myArray.sort(insensitiveSorter); trace(myArray); // Displays: California,camel,cardinal,Chicago
When sorting numbers, the standard sort( ) method produces unexpected results. Numbers are sorted "alphabetically" instead of numerically. After the following example, myArray is [1,12,2,3,4,43], not [1,2,3,4,12,43]:
myArray = [1, 12, 2, 3, 43, 4]; myArray.sort( ) trace (myArray); // Displays: 1,12,2,3,4,43 not 1,2,3,4,12,43
Here is a simple compare function that performs a numeric sort, instead of a string-based sort, even if the elements are strings, such as "1", "2", "3":
function numberSorter(a, b) { itemOne = parseInt(a); itemTwo = parseInt(b); if (itemOne > itemTwo) { return 1; } else if (itemOne < itemTwo) { return -1; } else { return 0 } }
You can use it as follows:
myArray = [1, 12, 2, 3, 43, 4]; myArray.sort(numberSorter); trace (myArray); // Displays: 1,2,3,4,12,43
In the numberSorter( ) function, the difference between the two numbers yields a positive result if a is greater than b, and a negative result if the opposite is true. It yields 0 if they are equal. Therefore, numeric comparisons of the previous type can be simplified as follows.
function numberSorter(a, b) { itemOne = parseInt(a); itemTwo = parseInt(b); return (itemOne - itemTwo); }
You can easily modify the sort function to sort the numbers in reverse order, as follows:
function reverseSorter(a, b) { itemOne = parseInt(a); itemTwo = parseInt(b); return (itemTwo - itemOne); }
Here is a full-fledged example that sorts the cars array by make and year:
// Create an array with elements that have some matching make properties but // different year and color properties. cars = new Array( ); cars.push({make: "Honda", year: 1997, color: "maroon"}); cars.push({make: "Chrysler", year: 2000, color: "beige"}); cars.push({make: "Mercedes", year: 1985, color: "blue"}); cars.push({make: "Fiat", year: 1983, color: "gray"}); cars.push({make: "Honda", year: 1982, color: "white"}); cars.push({make: "Chrysler", year: 1999, color: "green"}); cars.push({make: "Mercedes", year: 2002, color: "tan"}); cars.push({make: "Fiat", year: 1981, color: "brown"}); // Create the custom compare function. The function is always passed two elements as // parameters. It is convenient to call them a and b. function sorter(a, b) { // If the make property of a is larger than (meaning it comes alphabetically after) // the make property of b, return 1 to sort a after b. If the make property of a is // less than the make property of b, then return -1 to sort a before b. Otherwise // (if a.make and b.make are the same), perform the comparison on the year // property. We use String.toUpperCase( ) to ensure a case-insensitive comparison. // We also convert the year to an integer and use the aforementioned shortcut for // numeric comparison. makeOne = a.make.toUpperCase( ); makeTwo = b.make.toUpperCase( ); if (makeOne > makeTwo ) { return 1; } else if (makeOne < makeTwo) { return -1; } else { return (parseInt(a.year) - parseInt(b.year)) } } // Call the sort( ) method and pass it a reference to the sorter( ) compare function. cars.sort(sorter); // Loop through the array and output the results. for (var i = 0; i < cars.length; i++) { // Displays the results alphabetically by make, then by year: // A green 1999 Chrysler // A beige 2000 Chrysler // A brown 1981 Fiat // A gray 1983 Fiat // A white 1982 Honda // A maroon 1997 Honda // A blue 1985 Mercedes // A tan 2002 Mercedes trace("A " + cars[i].color + " " + cars[i].year + " " + cars[i].make); }