Accessibility

Flash Quick Start: Programming with ActionScript 3.0

Programming with arrays

Arrays are a fundamentally important data structure for programming. At their most basic, arrays are containers for sets of objects. Arrays make it mush easier to maintain and modify related objects. This is particularly evident when you have several variables that share something in common. For example, if you have a list of contacts, you can place them in an array, which then acts much like an address book - one that you can very easily search through, or extract specific entries from to make modifications.

The following sections describe array programming in more detail:

Types of arrays

The most common type of array is an indexed array. In this type, an index number is provided to any element that is added to the array. Arrays in ActionScript 3.0 are zero-based; the first element is assigned an index of 0, the second an index of 1, and so on. You can access individual elements in an indexed array by specifying the index inside a bracket operator ([]):

// Create a new array, adding three elements to it
var arr:Array = new Array("a", "b", "c");
trace(arr); // output: a,b,c

// Overwrite the third item (at index 2) with a new string
arr[2] = "aa";
// Set the third index to a new string
arr[3] = "bb";

trace(arr); // output: a,b,aa,cc

                      

Arrays can also contain other arrays. These are called multidimensional arrays. Arrays can visually be conceived as a single row, with each element being a column in the row. If an array contains an array for each element, this creates a two-dimesional array, which is analogous to a grid with many rows and many columns. A bitmap image can be described as a two-dimensional array, where each element is a row that contains elements for each column. Each of these columns contain color information for each pixel.

// Create a new array
var arr:Array = new Array();
arr[0] = new Array("a", "b", "c");
arr[1] = new Array("d", "e", "f");
arr[2] = new Array("g", "h", "i");

trace(arr); // output: a,b,c,d,e,f,g,h,i
trace(arr[0]); // output: a,b,c
trace(arr[0][0]); // output: a
trace(arr[0][1]); // output: b
trace(arr[0][2]); // output: c
trace(arr[2][2]); // output: i

                      

The final type of array is an associative array, which are also commonly called a hash or map. These arrays do not contain indexes, but instead reference elements by a key. In ActionScript 3.0, an associative array is functionally equivalent to an instance of the Object class. The key strings of an associative array are analogous to property names of an object. Therefore, you can create an associative array by using either Object or Array syntax:

// Create a new array
var indexedArray:Array = new Array();
// Assign index 0 to a new string
indexedArray[0] = "bob";
trace(indexedArray[0]); // output: bob
trace(indexedArray.length); // output: 1

// Create a new array
var associativeArr:Array = new Array();
// Assign a new string to key "name", making the array associative
associativeArr["name"] = "bob";
trace(associativeArr["name"]) // output: bob
trace(associativeArr.length); // output: 0 (length method unavailable to associative arrays)

var obj:Object = new Object();
obj.name = "bob";
trace(obj.name); // output: bob

                      

Note that regardless of how you create an associative array, it is an unordered set of name value pairs, and as such, it does not have the same capabilities as that of an indexed array. Once an array is passed a key value pair, that array can no longer use the length() method to determine how many elements are contained within.

Modifying the contents of an array

You can specify a new value to a particular index of an array by using the bracket operator, but you can also add or remove elements to the beginning or end of an array, using native methods of the Array class. To add an element to the end of an array, use the push() method. To add an element to the beginning of an array, use the unshift() method. Analogously, you can remove elements from either the beginning or end of an array, using the shift() and pop() methods, respectively. The following example shows the difference between these methods:

var arr:Array = new Array();
arr.push("green");
arr.push("blue");
arr.push("violet");
trace(arr); // output: green,blue,violet

arr.unshift("yellow");
arr.unshift("orange");
arr.unshift("red");
trace(arr); // output: red,yellow,orange,green,blue,violet

// Remove the last item from the array
var lastItem:String = arr.pop();
trace(lastItem); // output: violet
// Remove the first item from the array
var firstItem:String = arr.shift();
trace(firstItem); // output: red

trace(arr); // output: orange,yellow,green,blue

                      

You can add or remove elements from the middle of an array by using the splice() method. In either case, the first parameter of the splice() method is the index to begin adding or removing.

// Create an array with two strings
var arr:Array = new Array("black", "white");

// Add two to the beginning
arr.splice(0, 0, "red", "orange", "yellow");
                      

If you are adding elements, specify zero for the second parameter, followed by a commma-delimited list of elements to add:

// Add colors to the end
arr.splice(5, 0, "green", "blue", "violet");
                      

If you are deleting elements, specify the number to be deleted as the second parameter:

// Remove two in the middle, starting at the third index
arr.splice(3,2);
                      

You can create a new array out of an existing array using either the slice() or concat() methods. The slice() method returns an array that is a subset between two indices. The concat() method returns an array that is a merger of the arguments passed to it. The original array or arrays that are passed to either of these methods remain unchanged:

// Create a combined array without changing an initial array
var initialArray:Array = new Array("red", "orange", "yellow");
// Create an array that combines the initial array with three more strings
var combinedArray:Array = initialArray.concat("green", "blue", "violet");
// Create a subset of this array without changing the original
var slicedArray:Array = combinedArray.slice(3);

trace(initialArray); // output: red,orange,yellow
trace(combinedArray); // output: red,orange,yellow,green,blue,violet
trace(slicedArray); // output: green,blue,violet

                      

Sending elements of an array to callback functions

The Array class contains methods that simplify common tasks such as finding an element or modifying all elements within the array. This section will cover some of these methods in detail.

Five methods of the Array class use callback functions: every(), some(), forEach(), map(), and filter(). These methods expect a function as a parameter. Thhe specified function once for each element of the array. Every callback function specified for these methods should expect three parameters: the first is a reference to the element in the array, the second is the index of that element in the array, and the third is the array itself.

These callback functions can easily execute code based on each element in an array. For example, you can trace out each element in an array with customized formatting using the forEach() method:

var arr:Array = new Array(  { country:"Cameroon", continent:"Africa" },
                            { country:"Laos", continent:"Asia" },
                            { country:"Uruguay", continent:"South America" },
                            { country:"Romania", continent:"Europe" },
                            { country:"Canada", continent:"North America" } );

arr.forEach(traceContinent);


function traceContinent(element:*, index:int, arr:Array):void {

    trace(element.country + " is found in " + element.continent);
}
                      

The map() method is similar to forEach(), but it returns a new array composed of elements that the callback function returns. This example creates a DataProvider instance that is used to populate a list with a formatted string from elements of another array (note that you will need the List component to be in the library of the FLA in order to compile):

import fl.controls.Button;
import fl.controls.DataGrid; import fl.controls.List; import fl.data.DataProvider; var famousWorks:Array = new Array( { author:"Homer", work:"The Iliad" }, { author:"Jules Verne", work:"Journey to the Center of the Earth" }, { author:"James Joyce", work:"Ulysses" }, { author:"John Steinbeck", work:"Grapes of Wrath" }, { author:"Allen Ginsberg", work:"Howl" } ); // create grid to show initial array var grid:DataGrid = new DataGrid(); grid.width = 350; grid.height = 125; grid.move(10, 10); grid.dataProvider = new DataProvider(famousWorks); addChild(grid); // create list for formatted output var list:List = new List(); list.width = 350; list.move(10, 180); list.rowCount = famousWorks.length; addChild(list); // create button to trigger the map method var mapBtn:Button = new Button(); mapBtn.x = 80; mapBtn.y = 10 + grid.height + 10; mapBtn.width = 200; mapBtn.label = "Format using Array.map()"; addChild(mapBtn); mapBtn.addEventListener(MouseEvent.CLICK, onMapButtonClick); function onMapButtonClick(evt:MouseEvent):void { // generate a formmatted list using the map() method var formattedWorks:Array = famousWorks.map(formatFamousWork); var dp:DataProvider = new DataProvider(formattedWorks); list.dataProvider = dp; } function formatFamousWork(element:*, index:int, arr:Array):String { return element.work + " (by " + element.author + ")"; }

This example is illustrated below:

AlertThis content requires Flash

Download the free Flash Player now!

Get Adobe Flash Player

To download the source files for this example, click here.

To create a subset of another array, you can use the filter() method. In a callbck function to a filter() call, you must return true if the element should be in the new array or false if the element should be excluded. The following example generates an array of 100 random numbers from 0 to 100 and uses the filter() method to create a subset of all of the numbers that are larger than 90:

var arr:Array = new Array();

var totalElements:uint = 100;
for(var i:uint = 0; i<totalElements; i++) {

    arr[i] = Math.round(Math.random()*100);
}

function isLargerThan90(element:*, index:int, arr:Array):Boolean {
    return element > 90;

}
var highestNumbers:Array = arr.filter(isLargerThan90);
trace(highestNumbers);
                      

The every() and some() methods also expect a Boolean value from their callback functions. The every() method executes the callback function for each element in the array until the callback function returns false. Likewise, the some() method executes the callback function for each element in the array until the callback function returns true. This beahvior can be useful to determine if the array meets a particular criteria. The following example determines if an array is composed entirely of strings:

var arr:Array = new Array();
var totalElements:uint = 1000;

for(var i:uint = 0; i<totalElements; i++) {
    arr[i] = "name";
}

trace("Array is entirely composed of strings: " + arr.every(hasOnlyStrings));

function hasOnlyStrings(element:*, index:int, arr:Array):Boolean {
    return element is String;
}

arr[42] = 81; // change one element to a number

trace("Array is entirely composed of strings: " + arr.every(hasOnlyStrings));
                      

Searching for elements in arrays

You can search for an element in an array using the indexOf() or lastIndexOf() methods. These methods use optimized search algorithms, and will typically perform better than custom search loops. The following example compares the performance of searching using the indexOf() methods versus searching by looping and searching by using the for each construct:

// assumes having two components on the screen:
// 1. A TextArea named outputTxt
// 2. A Button named startBtn
var loopCount:Number = Math.pow(10,6); var loopingTally:uint = 0; var forEachTally:uint = 0; var indexOfTally:uint = 0; var testsToMake:uint = 5; // Create a large array composed entirely of zeroes var a:Array = new Array(); for (var i:uint=0; i<loopCount; i++) { a[i] = 0; } // Start a timer that will start a new test every half-second, up to the total tests needed var t:Timer = new Timer(500,testsToMake); // Run the makeTest function every time the timer ticks t.addEventListener(TimerEvent.TIMER,makeTest); // When the timer has completed, run the showResults function t.addEventListener(TimerEvent.TIMER_COMPLETE,showResults); t.start(); function findByLooping(toSearchFor:Number):uint { var start:int = getTimer(); for (i=0; i<loopCount; i++) { if(a[i] == toSearchFor) { var end:int = getTimer(); var elapsed:int = end - start; trace ("Found " + toSearchFor + " by looping at index: " + i + " time: " + String(elapsed)); break; } } return elapsed; } function findByForEach(toSearchFor:Number):uint { var start:int = getTimer(); for each(var entry:Number in a) { if(entry == toSearchFor) { var end:int = getTimer(); var elapsed:int = end - start; trace ("Found " + toSearchFor + " in for each loop at time: " + String(elapsed)); break; } } return elapsed; } function findByIndexOf(toSearchFor:Number):uint { var start:int = getTimer(); var foundIndex:int = a.indexOf(toSearchFor); var end:int = getTimer(); var elapsed:int = end - start; trace ("Found " + toSearchFor + " by indexOf() at index: " + foundIndex + " time: " + String(elapsed)); return elapsed; } function makeTest(e:TimerEvent):void { // Get a random number var randomNumber:Number = Math.random(); // Assign it to a random index in our dummy array a[Math.floor(Math.random()*loopCount)] = randomNumber; // Find it, timing various methods loopingTally += findByLooping(randomNumber); forEachTally += findByForEach(randomNumber); indexOfTally += findByIndexOf(randomNumber); } function showResults(e:TimerEvent):void { trace("== Average search time by looping: " + loopingTally/testsToMake); trace("== Average search time by for each: " + forEachTally/testsToMake); trace("== Average search time by indexOf: " + indexOfTally/testsToMake); }

Here is some sample output from this application:

== Average search time by looping: 134.6
== Average search time by for each: 26
== Average search time by indexOf: 6.4

As you can see searching by using the indexOf() method is considerably faster than the other two approaches.

Click on the Start button to run the tests in the example below.

AlertThis content requires Flash

Download the free Flash Player now!

Get Adobe Flash Player

To download the source files for this example, click here.

For more information on how to sort an array, see the ActionScript 3.0 Language Reference, which contains detailed coverage of how to use the sort() and sortOn() methods. You can download a sample of a PlayList application that uses many of the array concepts described in this article from the samples tab in the Flash Developer Center. The PlayList application files can be found in the Samples/PlayList folder. The PlayList sample is described in the Programming ActionScript 3.0 book.


Related Flash Quick Starts


About the author

Buck DeFore is a developer and writer for the Adobe documentation team.