ActionScript 3.0 Cookbook: Chapter 5, Arrays
Pages: 1, 2, 3, 4, 5, 6, 7, 8

Frequently, you may want to get the sorted order of an array's elements, but you don't want to change the original array because other parts of your application may depend on the existing order. For example, if you have parallel arrays, and you sort one array, its relationship with the other arrays is no longer valid. In such scenarios the Array.RETURNINDEXEDARRAY constant is very helpful. It allows you to return a new array containing the indices of the elements of the original array in sorted order, as illustrated in the following code:

var words:Array = ["tricycle", "relative", "aardvark", "jargon"];
var indices:Array = words.sort(Array.RETURNINDEXEDARRAY);
trace(words);   // Displays: tricycle,relative,aardvark,jargon
trace(indices); // Displays: 2,3,1,0
for(var i:int = 0; i < words.length; i++) {
  /* Displays:
     aardvark
     jargon
     relative
     tricycle
  */
  trace(words[indices[i]]);
}

You aren't limited to one sort modifier at a time. You can combine the combine the constants using the bitwise OR operator (|). The following code illustrates a case-insensitive, descending sort:

var words:Array = ["Tricycle", "relative", "aardvark", "jargon"];
words.sort(Array.CASEINSENSITIVE | Array.DESCENDING);
trace(words);   // Displays: Tricycle,relative,jargon,aardvark

Sometimes you want to reverse the order of the elements in an array. The sort( ) method allows you to run ascending, descending, case-sensitive, case-insensitive, and numeric sorts, but it does not allow you to simply reverse the order of the elements. Instead, you can use the reverse( ) method. The reverse( ) method does just what its name suggests; it reverses the order of the elements:

var words:Array = ["tricycle", "relative", "aardvark", "jargon"];
words.reverse( );
trace(words);   // Displays: jargon,aardvark,relative,tricycle

The preceding portion of this recipe described how to sort arrays in which the elements are strings or numbers. You can also sort arrays of objects of any type using the sortOn( ) method. The sortOn( ) method requires a string parameter specifying the name of the property on which to sort the elements:

var cars:Array = 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"});
// Sort the cars array according to the year property 
// of each element.cars.sortOn("year");
for (var i:int = 0; i < cars.length; i++) {
  /* Displays:
     gray    1983  Fiat
     blue    1985  Mercedes
     maroon  1997  Honda
     beige   2000  Chrysler
  */
  trace(cars[i].color + "\\t" + 
        cars[i].year + "\\t" + 
        cars[i].make);
}

The sortOn( ) method also has the ability to sort on more than one field. You can do so by specifying an array of fields on which to sort. The elements are then sorted on those fields in the specified order. To understand how it works, take a look at the following examples:

var cars:Array = 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: 1992, color: "silver"});
cars.push({make: "Chrysler", year: 1968, color: "gold"});
cars.push({make: "Mercedes", year: 1975, color: "green"});
cars.push({make: "Fiat",     year: 1983, color: "black"});
cars.push({make: "Honda",    year: 2001, color: "blue"});
cars.push({make: "Chrysler", year: 2004, color: "orange"});
cars.push({make: "Mercedes", year: 2000, color: "white"});
cars.push({make: "Fiat",     year: 1975, color: "yellow"});
     
// Sort the cars array according to the year property 
// of each element, then by the make.
cars.sortOn(["year", "make"]);
     
for (var i:int = 0; i < cars.length; i++) {
  /* Displays:
     gold     1968    Chrysler
     yellow   1975    Fiat
     green    1975    Mercedes
     black    1983    Fiat
     gray     1983    Fiat
     blue     1985    Mercedes
     silver   1992    Honda
     maroon   1997    Honda
     beige    2000    Chrysler
     white    2000    Mercedes
     blue     2001    Honda
     orange   2004    Chrysler
  */
  trace(cars[i].color + "\\t" + 
        cars[i].year + "\\t" + 
        cars[i].make);
}

The next example sorts the same array first by make, then by year--notice what the effect is:

cars.sortOn(["make", "year"]);
     
for (var i:int = 0; i < cars.length; i++) {
  /* Displays:
     gold    1968    Chrysler
     beige   2000    Chrysler
     orange  2004    Chrysler
     yellow  1975    Fiat
     black   1983    Fiat
     gray    1983    Fiat
     silver  1992    Honda
     maroon  1997    Honda
     blue    2001    Honda
     green   1975    Mercedes
     blue    1985    Mercedes
     white   2000    Mercedes  
  */
  trace(cars[i].color + "\\t" + 
        cars[i].year + "\\t" + 
        cars[i].make);
}

As with the sort( ) method, the sortOn( ) method supports sort modifiers. You can use the Array constants to sort in descending, case-insensitive, and numeric order. You can also, as with the sort( ) method, run a unique sort and return an array of sorted indices rather than affecting the original array. The following example sorts cars in descending order:

cars.sortOn("year", Array.DESCENDING);
     
for (var i:int = 0; i < cars.length; i++) {
  /* Displays:
     beige   2000  Chrysler
     maroon  1997  Honda
     blue    1985  Mercedes
     gray    1983  Fiat
  */
  trace(cars[i].color + "\\t" + 
        cars[i].year + "\\t" + 
        cars[i].make);
}

This excerpt is from ActionScript 3.0 Cookbook. Well before Ajax and Windows Presentation Foundation, Macromedia Flash provided the first method for building "rich" web pages. Now, Adobe is making Flash a full-fledged development environment, and learning ActionScript 3.0 is key. That's a challenge for even the most experienced Flash developer. This Cookbook offers more than 300 solutions to solve a wide range of coding dilemmas, so you can learn to work with the new version right away.

buy button

Sorted arrays can be useful in many scenarios. For example, if you want to display the elements of an array in a UI component or a text field, you often want to list the elements in alphabetical order.

Unless you use the Array.RETURNINDEXEDARRAY constant, the sort( ) and sortOn( ) methods make changes to the order of the original array; they do not return a new array.

See Also

Recipe 5.8 to make a separate copy of an array on which you can perform destructive operations. Recipe 5.11 for details on custom sorting.

Section 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.

Pages: 1, 2, 3, 4, 5, 6, 7, 8

Next Pagearrow