Third, if you call the constructor and pass a list of elements as parameters, an array is created with elements corresponding to each of the parameters. The following code passes three arguments to the Array constructor:
var names:Array = new Array("John", "Jane", "David");
trace(names.length); // output: 3
trace(names[0]); // output: John
trace(names[1]); // output: Jane
trace(names[2]); // output: David
You can also create arrays with array literals or object literals. An array literal can be assigned directly to an array variable, as shown in the following example:
var names:Array = ["John", "Jane", "David"];
Inserting array elements
Three of the Array class methods—
push(), unshift(), and splice()—allow you to insert elements into an array. The push() method appends one or more elements to the end of an array. In other words, the last element inserted into the array using the push() method will have the highest index number. The unshift() method inserts one or more elements at the
beginning of an array, which is always at index number 0. The splice() method will insert any number of items at a specified index in the array.
The following example demonstrates all three methods. An array named planets is created to store the names of the planets in order of proximity to the Sun. First, the push() method is called to add the initial item, Mars. Second, the unshift() method is called to insert the item that belongs at the front of the array, Mercury. Finally, the splice() method is called to insert the items Venus and Earth after Mercury, but before Mars.
The second argument sent to splice(), the integer 0, indicates that no items should be deleted. Finally, the third and fourth arguments sent to splice(), Venus and Earth, are the items to be inserted.
var planets:Array = new Array();
planets.push("Mars"); // array contents: Mars
planets.unshift("Mercury"); // array contents: Mercury,Mars
planets.splice(1, 0, "Venus", "Earth");
trace(planets); // array contents: Mercury,Venus,Earth,Mars
The push() and unshift() methods both return an unsigned integer that represents the length of the modified array. The splice() method returns an empty array when used to insert elements, which may seem strange, but makes more sense in light of the splice() method’s versatility. You can use the splice() method not only to insert elements into an array, but also to remove elements from an array. When used to remove elements, the splice() method returns an array containing the elements removed.
Removing array elements
Three methods of the Array class—pop(), shift(), and splice()—allow you to remove elements from an array. The pop() method removes an element from the end of the array. In other words, it removes the element at the highest index number. The shift() method removes an element from the beginning of the array, which means that it always removes the element at index number 0. The splice() method, which can also be used to insert elements, removes an arbitrary number of elements starting at the index number specified by the first argument sent to the method.
The following example uses all three methods to remove elements from an array. An array named oceans is created to store the names of large bodies of water. Some of the names in the array are lakes rather than oceans, so they need to be removed.
First, the splice() method is used to remove the items Aral and Superior, and insert the items Atlantic and Indian. The first argument sent to splice(), the integer 2, indicates that the operation should start with the third item in the list, which is at index 2.
The second argument, 2, indicates that two items should be removed. The remaining arguments, Atlantic and Indian, are values to be inserted at index 2.
Second, the pop() method is used to remove last element in the array, Huron. And third, the shift() method is used to remove the first item in the array, Victoria.
var oceans:Array = ["Victoria", "Pacific", "Aral", "Superior", "Indian",
"Huron"];
oceans.splice(2, 2, "Arctic", "Atlantic"); // replaces Aral and Superior
oceans.pop(); // removes Huron
oceans.shift(); // removes Victoria
trace(oceans); // output: Pacific,Arctic,Atlantic,Indian
The pop() and shift() methods both return the item that was removed. The data type of the return value is Object because arrays can hold values of any data type. The splice() method returns an array containing the values removed. You can change the oceans array example so that the call to splice() assigns the array to a new array variable, as shown in the following example:
var lakes:Array = oceans.splice(2, 2, "Arctic", "Atlantic");
trace(lakes); // output: Aral,Superior
You may come across code that uses the delete operator on an array element. The delete operator sets the value of an array element to undefined, but it does not remove the element from the array. For example, the following code uses the delete operator on the third element in the oceans array, but the length of the array remains 5:
var oceans:Array = ["Arctic", "Pacific", "Victoria", "Indian", "Atlantic"];
delete oceans[2];
trace(oceans); // output: Arctic,Pacific,,Indian,Atlantic
trace(oceans[2]); // output: undefined
trace(oceans.length); // output: 5
You can truncate an array using an array’s length property. If you set the length property ofan array to a length that is less than the current length of the array, the array is truncated, removing any elements stored at index numbers higher than the new value of length minus 1.
For example, if the oceans array were sorted such that all valid entries were at the beginning of the array, you could use the length property to remove the entries at the end of the array, as shown in the following code:
var oceans:Array = ["Arctic", "Pacific", "Victoria", "Aral", "Superior"];
oceans.length = 2;
trace(oceans); // output: Arctic,Pacific
Sorting an array
There are three methods—reverse(), sort(), and sortOn()—that allow you to change the order of an array, either by sorting or reversing the order. All of these methods modify the existing array. The reverse() method changes the order of the array such that the last element becomes the first element, the penultimate element becomes the second element, and so on. The sort() method allows you to sort an array in a variety of predefined ways, and even allows you to create custom sorting algorithms. The sortOn() method allows you to sort an indexed array of objects that have one or more common properties that can be used as sort keys.
The reverse() method takes no parameters and does not return a value, but allows you to toggle the order of your array from its current state to the reverse order. The following example reverses the order of the oceans listed in the oceans array:
var oceans:Array = ["Arctic", "Atlantic", "Indian", "Pacific"];
oceans.reverse();
trace(oceans); // output: Pacific,Indian,Atlantic,Arctic
The sort() method rearranges the elements in an array using the default sort order. The default sort order has the following characteristics:
■ The sort is case-sensitive, which means that uppercase characters precede lowercase characters. For example, the letter D precedes the letter b.
■ The sort is ascending, which means that lower character codes (such as A) precede higher character codes (such as B).
■ The sort places identical values adjacent to each other but in no particular order.
■ The sort is string-based, which means that elements are converted to strings before they are compared (for example, 10 precedes 3 because the string "1" has a lower character code than the string "3" has).
You may find that you need to sort your array without regard to case, or in descending order, or perhaps your array contains numbers that you want to sort numerically instead of alphabetically. The sort() method has an options parameter that allows you to alter each characteristic of the default sort order. The options are defined by a set of static constants in the Array class, as shown in the following list:
■ Array.CASEINSENSITIVE: This option makes the sort disregard case. For example, the lowercase letter b precedes the uppercase letter D.
■ Array.DESCENDING: This reverses the default ascending sort. For example, the letter B precedes the letter A.
■ Array.UNIQUESORT: This causes the sort to abort if two identical values are found.
■ Array.NUMERIC: This causes numerical sorting, so that 3 precedes 10.
The following example highlights some of these options. An array named poets is created that is sorted using several different options.
var poets:Array = ["Blake", "cummings", "Angelou", "Dante"];
poets.sort(); // default sort
trace(poets); // output: Angelou,Blake,Dante,cummings
poets.sort(Array.CASEINSENSITIVE);
trace(poets); // output: Angelou,Blake,cummings,Dante
poets.sort(Array.DESCENDING);
trace(poets); // output: cummings,Dante,Blake,Angelou
poets.sort(Array.DESCENDING | Array.CASEINSENSITIVE); // use two options
trace(poets); // output: Dante,cummings,Blake,Angelou
You can also write your own custom sort function, which you can pass as a parameter to the sort() method. For example, if you have a list of names in which each list element contains a person’s full name, but you want to sort the list by last name, you must use a custom sort function to parse each element and use the last name in the sort function.
The following code shows how this can be done with a custom function that is used as a parameter to the Array.sort() method:
var names:Array = new Array("John Q. Smith", "Jane Doe", "Mike Jones");
function orderLastName(a, b):int {
var lastName:RegExp = /\b\S+$/;
var name1 = a.match(lastName);
var name2 = b.match(lastName);
if (name1 < name2) {
return -1;
} else if (name1 > name2) {
return 1;
} else {
return 0;
}
}
trace(names); // output: John Q. Smith,Jane Doe,Mike Jones
names.sort(orderLastName);
trace(names); // output: Jane Doe,Mike Jones,John Q. Smith
The custom sort function orderLastName() uses a regular expression to extract the last name from each element to use for the comparison operation. The function identifier orderLastName is used as the sole parameter when calling the sort() method on the names array. The sort function accepts two parameters, a and b, because it works on two array elements at a time. The sort function’s return value indicates how the elements should be sorted:
■ A return value of -1 indicates that the first parameter, a, precedes the second parameter, b.
■ A return value of 1 indicates that the second parameter, b, precedes the first, a.
■ A return value of 0 indicates that the elements have equal sorting precedence.
The sortOn() method is designed for indexed arrays with elements that contain objects.
These objects are expected to have at least one common property that can be used as the sort key. The use of the sortOn() method for arrays of any other type yields unexpected results.
The following example revises the poets array so that each element is an object instead of a string. Each object holds both the poet’s last name and year of birth.
var poets:Array = new Array();
poets.push({name:"Angelou", born:"1928"});
poets.push({name:"Blake", born:"1757"});
poets.push({name:"cummings", born:"1894"});
poets.push({name:"Dante", born:"1265"});
poets.push({name:"Wang", born:"701"});
You can use the sortOn() method to sort the array by the born property. The sortOn() method defines two parameters, fieldName and options. The fieldName argument must be specified as a string. In the following example, sortOn() is called with two arguments, "born" and Array.NUMERIC. The Array.NUMERIC argument is used to ensure that the sort is done numerically instead of alphabetically. This is a good practice even when all the numbers have the same number of digits because it ensures that the sort will continue to behave as expected if a number with fewer or more digits is later added to the array.
poets.sortOn("born", Array.NUMERIC);
for (var i:int = 0; i < poets.length; ++i) {
trace(poets[i].name, poets[i].born);
}
/* output:
Wang 701
Dante 1265
Blake 1757
cummings 1894
Angelou 1928
*/
Generally, the sort() and sortOn() methods modify an array. If you wish to sort an array without modifying the existing array, pass the Array.RETURNINDEXEDARRAY constant as part of the options parameter. This option directs the methods to return a new array that reflects the sort and to leave the original array unmodified. The array returned by the methods is a simple array of index numbers that reflects the new sort order and does not contain any elements from the original array.
For example, to sort the poets array by birth year without modifying the array, include the Array.RETURNINDEXEDARRAY constant as part of the argument passed for the options parameter.
The following example stores the returned index information in an array named indices and uses the indices array in conjunction with the unmodified poets array to output the poets in order of birth year:
var indices:Array;
indices = poets.sortOn("born", Array.NUMERIC | Array.RETURNINDEXEDARRAY);
for (var i:int = 0; i < indices.length; ++i) {
var index:int = indices[i];
trace(poets[index].name, poets[index].born);
}
/* output:
Wang 701
Dante 1265
Blake 1757
cummings 1894
Angelou 1928
*/
Querying an array
The remaining four methods of the Array class—concat(), join(), slice(), toString()—all query the array for information, but do not modify the array. The concat() and slice() methods both return new arrays, while the join() and toString() methods both return strings. The concat() method takes a new array or list of elements as arguments and combines it with the existing array to create a new array. The slice() method has two parameters, aptly named startIndex and an endIndex, and returns a new array containing a copy of the elements “sliced” from the existing array.
The slice begins with the element at startIndex and ends with the element just before endIndex. That bears repeating: the element at endIndex is not included in the return value.
The following example uses concat() and slice() to create new arrays using elements of other arrays:
var array1:Array = ["alpha", "beta"];
var array2:Array = array1.concat("gamma", "delta");
trace(array2); // output: alpha,beta,gamma,delta
var array3:Array = array1.concat(array2);
trace(array3); // output: alpha,beta,alpha,beta,gamma,delta
var array4:Array = array3.slice(2,5);
trace(array4); // output: alpha,beta,gamma
You can use the join() and toString() methods to query the array and return its contents as a string. If no parameters are used for the join() method, the two methods behave identically—they return a string containing a comma-delimited list of all elements in the array. The join() method, unlike the toString() method, accepts a parameter named delimiter, which allows you to choose the symbol to use as a separator between each element in the returned string.
The following example creates an array called rivers and calls both join() and toString() to return the values in the array as a string. The toString() method is used to return comma-separated values (riverCSV), while the join() method is used to return values separated by the + character.
var rivers:Array = ["Nile", "Amazon", "Yangtze", "Mississippi"];
var riverCSV:String = rivers.toString();
trace(riverCSV); // output: Nile,Amazon,Yangtze,Mississippi
var riverPSV:String = rivers.join("+");
trace(riverPSV); // output: Nile+Amazon+Yangtze+Mississippi
One issue to be aware of with the join() method is that any nested arrays are always returned with comma-separated values, no matter what separator you specify for the main array elements, as the following example shows:
var nested:Array = ["b","c","d"];
var letters:Array = ["a",nested,"e"];
var joined:String = letters.join("+");
trace(joined); // output: a+b,c,d+e
Extending the Array class
The Array class is one of the few core classes that is not final, which means that you can create your own subclass of Array. This section provides an example of how to create a subclass of Array and discusses some of the issues that can arise during the process.
As mentioned previously, arrays in ActionScript are not typed, but you can create a subclass of Array that accepts elements of only a specific data type. The example in the following sections defines an Array subclass named TypedArray that limits its elements to values of the data type specified in the first parameter.
The TypedArray class is presented merely as an example of how to extend the Array class and may not be suitable for production purposes for several reasons. First, type checking occurs at run time rather than at compile time. Second, when a TypedArray method encounters a mismatch, the mismatch is ignored and no exception is thrown, although the methods can be easily modified to throw exceptions. Third, the class cannot prevent the use of the array access operator to insert values of any type into the array.Fourth, the coding style favors simplicity over performance optimization.
Declaring the subclass
Use the extends keyword to indicate that a class is a subclass of Array. A subclass of Array should use the dynamic attribute, just as the Array class does. Otherwise, your subclass will not function properly.
The following code shows the definition of the TypedArray class, which contains a constant to hold the data type, a constructor method, and the four methods that are capable of adding elements to the array. The code for each method is omitted in this example, but is delineated and explained fully in the sections that follow:
public dynamic class TypedArray extends Array {
private const dataType:Class;
public function TypedArray(...args) {
}
AS3 override function concat(...args):Array {
}
AS3 override function push(...args):uint {
}
AS3 override function splice(...args) {
}
AS3 override function unshift(...args):uint {
}
}
The four overridden methods all use the AS3 namespace instead of the public attribute because this example assumes that the compiler option -as3 is set to true and the compiler option -es is set to false. These are the default settings for Adobe Flex Builder 2.
If you are an advanced developer who prefers to use prototype inheritance, you can make two minor changes to the TypedArray class to make it compile with the compiler option -es set to true. First, remove all occurrences of the override attribute and replace the AS3 namespace with the public attribute. Second, substituteArray.prototype for all four occurrences of super.
TypedArray constructor
The subclass constructor poses an interesting challenge because the constructor must accept a list of arguments of arbitrary length. The challenge is how to pass the arguments on to the superconstructor to create the array. If you pass the list of arguments as an array, the superconstructor considers it a single argument of type Array and the resulting array is always 1 element long. The traditional way to handle pass-through argument lists is to use the Function.apply() method, which takes an array of arguments as its second parameter but converts it to a list of arguments when executing the function. Unfortunately, the Function.apply() method cannot be used with constructors.
The only option left is to recreate the logic of the Array constructor in the TypedArray constructor. The following code shows the algorithm used in the Array class constructor, which you can reuse in your Array subclass constructor:
public dynamic class Array {
public function Array(...args) {
var n:uint = args.length
if (n == 1 && (args[0] is Number))
{
var dlen:Number = args[0];
var ulen:uint = dlen
if (ulen != dlen)
throw new RangeError("Array index is not a 32-bit unsigned integer ("+dlen+")")
length = ulen;
}
else
{
length = n;
for (var i:int=0; i < n; i++) {
this[i] = args[i]
}
}
}
}
The TypedArray constructor shares most of the code from the Array constructor, with only four changes to the code. First, the parameter list includes a new required parameter of type Class that allows specification of the array’s data type. Second, the data type passed to the constructor is assigned to the dataType variable. Third, in the else statement, the value of the length property is assigned after the for loop so that length includes only arguments that are the proper type. Fourth, the body of the for loop uses the overridden version of the push() method so that only arguments of the correct data type are added to the array. The following example shows the TypedArray constructor function:
public dynamic class TypedArray extends Array {
private var dataType:Class;
public function TypedArray(typeParam:Class, ...args) {
dataType = typeParam;
var n:uint = args.length
if (n == 1 && (args[0] is Number))
{
var dlen:Number = args[0];
var ulen:uint = dlen
if (ulen != dlen)
throw new RangeError("Array index is not a 32-bit unsigned integer ("+dlen+")")
length = ulen;
}
else
{
for (var i:int=0; i < n; i++) {
// type check done in push()
this.push(args[i])
}
length = this.length;
}
}
}
TypedArray overridden methods
The TypedArray class overrides the four methods of the Array class that are capable of adding elements to an array. In each case, the overridden method adds a type check that prevents the addition of elements that are not the correct data type. Subsequently, each method calls the superclass version of itself.
The push() method iterates through the list of arguments with a for..in loop and does a type check on each argument. Any argument that is not the correct type is removed from the args array with the splice() method. After the for..in loop ends, the args array contains values only of type dataType. The superclass version of push() is then called with the updated args array, as the following code shows:
AS3 override function push(...args):uint {
for (var i:* in args) {
if (!(args[i] is dataType)) {
args.splice(i,1);
}
}
return (super.push.apply(this, args));
}
The concat() method creates a temporary TypedArray named passArgs to store the arguments that pass the type check. This allows the reuse of the type check code that exists in the push() method. A for..in loop iterates through the args array, and calls push() on each argument. Because passArgs is typed as TypedArray, the TypedArray version of push() is executed. The concat() method then calls its own superclass version, as the following code shows:
AS3 override function concat(...args):Array {
var passArgs:TypedArray = new TypedArray(dataType);
for (var i:* in args) {
// type check done in push()
passArgs.push(args[i]);
}
return (super.concat.apply(this, passArgs));
}
The splice() method takes an arbitrary list of arguments, but the first two arguments always refer to an index number and the number of elements to delete. This is why the overridden splice() method does type checking only for args array elements in index positions 2 or higher. One point of interest in the code is that there appears to be a recursive call to splice() inside the for loop, but this is not a recursive call because args is of type Array rather than TypedArray, which means that the call to args.splice() is a call to the superclass version of the method. After the for..in loop concludes, the args array contains only values of the correct type in index positions 2 or higher, and splice() calls its own superclass version, as shown in the following code:
AS3 override function splice(...args):* {
if (args.length > 2) {
for (var i:int=2; i< args.length; i++) {
if (!(args[i] is dataType)) {
args.splice(i,1);
}
}
}
return (super.splice.apply(this, args));
}
The unshift() method, which adds elements to the beginning of an array, also accepts an arbitrary list of arguments. The overridden unshift() method uses an algorithm very similar to that used by the push() method, as shown in the following example code:
AS3 override function unshift(...args):uint {
for (var i:* in args) {
if (!(args[i] is dataType)) {
args.splice(i,1);
}
}
return (super.unshift.apply(this, args));
}
}
Click here for more informations about ...