http://hi.baidu.com/lz0830/blog/item/4d63d09b0a8c56b2c8eaf472.html
http://hi.baidu.com/andy_tj/blog/item/bacaa3dbcc1cc463d0164e8c.html
【向数组尾端添加元素】
var array:Array = new Array();
array.push("a", "b");
//向数组尾端添加单一元素也可以这样:
array[array.length] = "c";
//如果以索引设定的元素不存在,数组本身会自动扩展以包含足够的元素数目.介于中间的元素会被设为undefined:
array[5] = "e";
trace(array[4]); //输出: undefined
【向数组开端添加元素】
var array:Array = ["a", "b"];
array.unshift("c", "d");
trace(array); //输出: c,d,a,b
【删除数组中第一个元素并返回该元素,使用shift()方法】
var letters:Array = new Array("a", "b", "c");
var firstLetter:String = letters.shift();
trace(letters); //输出: b,c
trace(firstLetter); //输出: a
【删除数组中最后一个元素并返回该元素的值,使用pop()方法】
var letters:Array = new Array("a", "b", "c");
trace(letters); //输出: a,b,c
var letter:String = letters.pop();
trace(letters); //输出: a,b
trace(letter); //输出: c
【删除数组中的元素,给数组添加新元素并返回删除的元素,使用splice()方法】
splice(startIndex:int, deleteCount:uint, ... values):Array
startIndex: 一个整数,它指定数组中开始进行插入或删除的位置处的元素的索引;
deleteCount: 一个整数,它指定要删除的元素数量;
... values: 用逗号分隔的一个或多个值的可选列表或数组,此列表或数组将插入到此数组中由 startIndex 参数指定的位置.
【查找数组中第一个相匹配的元素】
var array:Array = ["a", "b", "c", "d", "a", "b", "c", "d"];
var match:String = "b";
for(var i:int = 0; i < array.length; i++) {
if(array[i] == match) {
trace("Element with index " + i + " found to match " + match);
//输出: Element with index 1 found to match b
break;
}
}
【查找数组中最后一个相匹配的元素】
var array:Array = ["a", "b", "c", "d", "a", "b", "c", "d"];
var match:String = "b";
for(var i:int = array.length - 1; i >= 0; i--) {
if(array[i] == match) {
trace("Element with index " + i + " found to match " + match);
//输出: Element with index 5 found to match b
break;
}
}
【把字符串转成数组】
使用String.split()方法:
var list:String = "I am YoungBoy.";
var words:Array = list.split(" "); //以空格作为分隔符将字符串切割
trace(words); //输出: I,am,YoungBoy.
【把数组转成字符串】
使用String.join()方法:
var myArr:Array = new Array("one", "two", "three");
var myStr:String = myArr.join(" and ");
trace(myArr); //输出: one,two,three
trace(myStr); //输出: one and two and three
【使用对象数组处理相关数据】
var cars:Array = new Array();
cars.push({make:"Mike", year:1997, color:"blue"});
cars.push({make:"Kelly", year:1986, color:"red"});
for(var i:int = 0; i < cars.length; i++) {
trace(cars[i].make + " - " + cars[i].year + " - " + cars[i].color);
}
//输出:
// Mike - 1997 - blue
// Kelly - 1986 - red
【在数组中获取最小或最大值】
var scores:Array = [10, 4, 15, 8];
scores.sort(Array.NUMERIC);
trace("Minimum: " + scores[0]);
trace("Maximum: " + scores[scores.length - 1]);
【使用for ... in语句读取关联数组元素】
var myObject:Object = new Object();
myObject.name = "YoungBoy";
myObject.age = 20;
for(var i:String in myObject) {
trace(i + ": " + myObject[i]);
}
//输出: name: YoungBoy
// age: 20
注意: for ... in循环不会显示对象所有的内建属性.例如,循环会显示执行期间新增的特殊属性,但是,不会列出内建对象的方法,即使都是储存在对象属性内.
常见数组任务
本章介绍了以下常见的数组使用活动:
■ 创建索引数组
■ 添加和删除数组元素
■ 对数组元素进行排序
■ 提取数组的某些部分
■ 处理关联数组和字典
■ 处理多维数组
■ 复制数组元素
■ 创建数组子类
重要概念和术语
以下参考列表包含将会在本章中遇到的重要术语:
■ 数组 (Array):用作容器以将多个对象组合在一起的对象。
■ 关联数组 (Associative array):使用字符串键来标识各个元素的数组。
■ 字典 (Dictionary):其项目由一对对象(称为键和值)组成的数组。它使用键来标识单
个元素,而不是使用数字索引。
■ 元素 (Element):数组中的单个项目。
■ 索引 (Index):用于标识索引数组中的单个元素的数字“地址”。
索引数组191
■ 索引数组 (Indexed array):这是一种标准类型的数组,它将每个元素存储在编号元素中,
并使用数字(索引)来标识各个元素。
■ 键 (Key):用于标识关联数组或字典中的单个元素的字符串或对象。
■ 多维数组 (Multidimensional array):此数组包含的项目是数组,而不是单个值。
索引数组
索引数组存储一系列经过组织的单个或多个值,其中的每个值都可以通过使用一个无符号整
数值进行访问。第一个索引始终是数字 0,且添加到数组中的每个后续元素的索引以 1 为增
量递增。正如以下代码所示,可以调用 Array 类构造函数或使用数组文本初始化数组来创建
索引数组:
// 使用 Array 构造函数。
var myArray:Array = new Array();
myArray.push("one");
myArray.push("two");
myArray.push("three");
trace(myArray); // 输出:one,two,three
// 使用数组文本。
var myArray:Array = ["one", "two", "three"];
trace(myArray); // 输出:one,two,three
Array 类中还包含可用来修改索引数组的属性和方法。这些属性和方法几乎是专用于索引数
组而非关联数组的。
索引数组使用无符号 32 位整数作为索引号。索引数组的最大大小为 232-1,即
4,294,967,295。如果要创建的数组大小超过最大值,则会出现运行时错误。
192 处理数组
数组元素的值可以为任意数据类型。ActionScript 3.0 不支持“指定类型的数组”概念,也
就是说,不能指定数组的所有元素都属于特定数据类型。
本部分说明如何使用 Array 类创建和修改索引数组,首先讲的是如何创建数组。修改数组的
方法分为三类,包括如何插入元素、删除元素和对数组进行排序。最后一类中的方法将现有
数组当作只读数组,这些方法仅用于查询数组。所有查询方法都返回新的数组,而非修改现
有数组。本部分结尾讨论了如何扩展 Array 类。
创建数组
Array 构造函数的使用有三种方式。第一种,如果调用不带参数的构造函数,会得到空数组。
可以使用 Array 类的 length 属性来验证数组是否不包含元素。例如,以下代码调用不带参
数的 Array 构造函数:
var names:Array = new Array();
trace(names.length); // 输出:0
第二种,如果将一个数字用作 Array 构造函数的唯一参数,则会创建长度等于此数值的数
组,并且每个元素的值都设置为 undefined。参数必须为介于值 0 和 4,294,967,295 之间
的无符号整数。例如,以下代码调用带有一个数字参数的 Array 构造函数:
var names:Array = new Array(3);
trace(names.length); // 输出:3
trace(names[0]); // 输出:undefined
trace(names[1]); // 输出:undefined
trace(names[2]); // 输出:undefined
第三种,如果调用构造函数并传递一个元素列表作为参数,将创建具有与每个参数对应的元
素的数组。以下代码将三个参数传递给 Array 构造函数:
var names:Array = new Array("John", "Jane", "David");
trace(names.length); // 输出:3
trace(names[0]); // 输出:John
trace(names[1]); // 输出:Jane
trace(names[2]); // 输出:David
也可以创建具有数组文本或对象文本的数组。可以将数组文本直接分配给数组变量,如以下
示例所示:
var names:Array = ["John", "Jane", "David"];
索引数组193
插入数组元素
可以使用 Array 类的三种方法(push()、unshift() 和 splice())将元素插入数组。push()
方法用于在数组末尾添加一个或多个元素。换言之,使用 push() 方法在数组中插入的最后
一个元素将具有最大索引号。unshift() 方法用于在数组开头插入一个或多个元素,并且始
终在索引号 0 处插入。splice() 方法用于在数组中的指定索引处插入任意数目的项目。
下面的示例对所有三种方法进行了说明。它创建一个名为 planets 的数组,以便按照距离太
阳的远近顺序存储各个行星的名称。首先,调用 push() 方法以添加初始项 Mars。接着,调
用 unshift() 方法在数组开头插入项 Mercury。最后,调用 splice() 方法在 Mercury 之后
和 Mars 之前插入项 Venus 和 Earth。传递给 splice() 的第一个参数是整数 1,它用于指
示从索引 1 处开始插入。传递给 splice() 的第二个参数是整数 0,它表示不应删除任何项。
传递给 splice() 的第三和第四个参数 Venus 和 Earth 为要插入的项。
var planets:Array = new Array();
planets.push("Mars"); // 数组内容:Mars
planets.unshift("Mercury"); // 数组内容:Mercury,Mars
planets.splice(1, 0, "Venus", "Earth");
trace(planets); // 数组内容:Mercury,Venus,Earth,Mars
push() 和 unshift() 方法均返回一个无符号整数,它们表示修改后的数组长度。在用于插
入元素时,splice() 方法返回空数组,这看上去也许有点奇怪,但考虑到 splice() 方法的
多用途性,您便会觉得它更有意义。通过使用 splice() 方法,不仅可以将元素插入到数组
中,而且还可以从数组中删除元素。用于删除元素时,splice() 方法将返回包含被删除元素
的数组。
删除数组元素
可以使用 Array 类的三种方法(pop()、shift() 和 splice())从数组中删除元素。pop()
方法用于从数组末尾删除一个元素。换言之,它将删除位于最大索引号处的元素。shift()
方法用于从数组开头删除一个元素,也就是说,它始终删除索引号 0 处的元素。splice()
方法既可用来插入元素,也可以删除任意数目的元素,其操作的起始位置位于由发送到此方
法的第一个参数指定的索引号处。
以下示例使用所有三种方法从数组中删除元素。它创建一个名为 oceans 的数组,以便存储
较大水域的名称。数组中的某些名称为湖泊的名称而非海洋的名称,因此需要将其删除。
首先,使用 splice() 方法删除项 Aral 和 Superior,并插入项 Atlantic 和 Indian。传递
给 splice() 的第一个参数是整数 2,它表示应从列表中的第三个项(即索引 2 处)开始执
行操作。第二个参数 2 表示应删除两个项。其余两个参数 Atlantic 和 Indian 是要在索引
2 处插入的值。
194 处理数组
然后,使用 pop() 方法删除数组中的最后一个元素 Huron。最后,使用 shift() 方法删除数
组中的第一个项 Victoria。
var oceans:Array = ["Victoria", "Pacific", "Aral", "Superior", "Indian",
"Huron"];
oceans.splice(2, 2, "Arctic", "Atlantic"); // 替换 Aral 和 Superior
oceans.pop(); // 删除 Huron
oceans.shift(); // 删除 Victoria
trace(oceans); // 输出:Pacific,Arctic,Atlantic,Indian
pop() 和 shift() 方法均返回已删除的项。由于数组可以包含任意数据类型的值,因而返回
值的数据类型为 Object。splice() 方法将返回包含被删除值的数组。可以更改 oceans 数
组示例,以使 splice() 调用将此数组分配给新的数组变量,如以下示例所示:
var lakes:Array = oceans.splice(2, 2, "Arctic", "Atlantic");
trace(lakes); // 输出:Aral,Superior
您可能会遇到这样的代码,它在数组元素上使用 delete 运算符。delete 运算符用于将数组
元素的值设置为 undefined,但它不会从数组中删除元素。例如,下面的代码在 oceans 数
组的第三个元素上使用 delete 运算符,但此数组的长度仍然为 5:
var oceans:Array = ["Arctic", "Pacific", "Victoria", "Indian", "Atlantic"];
delete oceans[2];
trace(oceans); // 输出:Arctic,Pacific,,Indian,Atlantic
trace(oceans[2]); // 输出:undefined
trace(oceans.length); // 输出:5
可以使用数组的 length 属性截断数组。如果将数组的 length 属性设置为小于数组当前长
度的值,则会截断数组,在索引号高于 length 的新值减 1 处所存储的任何元素将被删除。
例如,如果 oceans 数组的排序是将所有有效项放在数组的开始处,则可以使用 length 属性
删除数组末尾的项,如以下代码所示:
var oceans:Array = ["Arctic", "Pacific", "Victoria", "Aral", "Superior"];
oceans.length = 2;
trace(oceans); // 输出:Arctic,Pacific
对数组排序
可以使用三种方法(reverse()、sort() 和 sortOn())通过排序或反向排序来更改数组的
顺序。所有这些方法都用来修改现有数组。reverse() 方法用于按照以下方式更改数组的顺
序:最后一个元素变为第一个元素,倒数第二个元素变为第二个元素,依此类推。sort() 方
法可用来按照多种预定义的方式对数组进行排序,甚至可用来创建自定义排序算法。
sortOn() 方法可用来对对象的索引数组进行排序,这些对象具有一个或多个可用作排序键
的公共属性。
索引数组195
reverse() 方法不带参数,也不返回值,但可以将数组从当前顺序切换为相反顺序。以下示
例颠倒了 oceans 数组中列出的海洋顺序:
var oceans:Array = ["Arctic", "Atlantic", "Indian", "Pacific"];
oceans.reverse();
trace(oceans); // 输出:Pacific,Indian,Atlantic,Arctic
sort() 方法按照“默认排序顺序”重新安排数组中的元素。默认排序顺序具有以下特征:
■ 排序区分大小写,也就是说大写字符优先于小写字符。例如,字母 D 优先于字母 b。
■ 排序按照升序进行,也就是说低位字符代码(例如 A)优先于高位字符代码(例如 B)。
■ 排序将相同的值互邻放置,并且不区分顺序。
■ 排序基于字符串,也就是说,在比较元素之前,先将其转换为字符串(例如,10 优先于
3,因为相对于字符串 "3" 而言,字符串 "1" 具有低位字符代码)。
您也许需要不区分大小写或者按照降序对数组进行排序,或者您的数组中包含数字,从而需
要按照数字顺序而非字母顺序进行排序。sort() 方法具有 options 参数,可通过该参数改
变默认排序顺序的各个特征。options 是由 Array 类中的一组静态常量定义的,如以下列表
所示:
■ Array.CASEINSENSITIVE:此选项可使排序不区分大小写。例如,小写字母 b 优先于大
写字母 D。
■ Array.DESCENDING:用于颠倒默认的升序排序。例如,字母 B 优先于字母 A。
■ Array.UNIQUESORT:如果发现两个相同的值,此选项将导致排序中止。
■ Array.NUMERIC:这会导致排序按照数字顺序进行,比方说 3 优先于 10。
以下示例重点说明了这些选项中的某些选项。它创建一个名为 poets 的数组,并使用几种不
同的选项对其进行排序。
var poets:Array = ["Blake", "cummings", "Angelou", "Dante"];
poets.sort(); // 默认排序
trace(poets); // 输出:Angelou,Blake,Dante,cummings
poets.sort(Array.CASEINSENSITIVE);
trace(poets); // 输出:Angelou,Blake,cummings,Dante
poets.sort(Array.DESCENDING);
trace(poets); // 输出:cummings,Dante,Blake,Angelou
poets.sort(Array.DESCENDING | Array.CASEINSENSITIVE); // 使用两个选项
trace(poets); // 输出:Dante,cummings,Blake,Angelou
196 处理数组
您也可以编写自定义排序函数,然后将其作为参数传递给 sort() 方法。例如,如果有一个
名称列表,其中每个列表元素都包含一个人的全名,但现在要按照姓来对列表排序,则必须
使用自定义排序函数解析每个元素,然后使用排序函数中的姓。以下代码说明如何使用作为
参数传递给 Array.sort() 方法的自定义函数来完成上述工作:
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); // 输出:John Q. Smith,Jane Doe,Mike Jones
names.sort(orderLastName);
trace(names); // 输出:Jane Doe,Mike Jones,John Q. Smith
自定义排序函数 orderLastName() 使用正则表达式从每个元素中提取姓,以用于比较操作。
针对 names 数组调用 sort() 方法时,函数标识符 orderLastName 用作唯一的参数。排序函
数接受两个参数 a 和 b,因为它每次对两个数组元素进行操作。排序函数的返回值指示应如
何对元素排序:
■ 返回值 -1 表示第一个参数 a 优先于第二个参数 b。
■ 返回值 1 表示第二个参数 b 优先于第一个参数 a。
■ 返回值为 0 表示元素具有相同的排序优先级。
sortOn() 方法是为具有包含对象的元素的索引数组设计的。这些对象应至少具有一个可用
作排序键的公共属性。如果将 sortOn() 方法用于任何其它类型的数组,则会产生意外结果。
以下示例修改 poets 数组,以使每个元素均为对象而非字符串。每个对象既包含诗人的姓又
包含诗人的出生年份。
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"});
索引数组197
可以使用 sortOn() 方法,按照 born 属性对数组进行排序。sortOn() 方法定义两个参数
fieldName 和 options。必须将 fieldName 参数指定为字符串。在以下示例中,使用两个参
数 "born" 和 Array.NUMERIC 来调用 sortOn()。Array.NUMERIC 参数用于确保按照数字顺
序进行排序,而不是按照字母顺序。即使所有数字具有相同的数位,这也是一种很好的做法,
因为当后来在数组中添加较少数位或较多数位的数字时,它会确保排序如期继续进行。
poets.sortOn("born", Array.NUMERIC);
for (var i:int = 0; i < poets.length; ++i)
{
trace(poets[i].name, poets[i].born);
}
/* 输出:
Wang 701
Dante 1265
Blake 1757
cummings 1894
Angelou 1928
*/
通常,sort() 和 sortOn() 方法用来修改数组。如果要对数组排序而又不修改现有数组,请将
Array.RETURNINDEXEDARRAY 常量作为 options 参数的一部分进行传递。此选项将指示方法返
回反映排序的新数组同时保留原始数组原封不动。方法返回的数组为由反映新排序顺序的索引
号组成的简单数组,不包含原始数组的任何元素。例如,如果要根据出生年份对 poets 数组排
序,同时不对数组进行修改,请在传递的 options 参数中包括 Array.RETURNINDEXEDARRAY
常量。
以下示例将返回的索引信息存储在名为 indices 的数组中,然后使用 indices 数组和未修
改的 poets 数组按出生年份输出诗人:
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);
}
/* 输出:
Wang 701
Dante 1265
Blake 1757
cummings 1894
Angelou 1928
*/
198 处理数组
查询数组
Array 类中的其余四种方法 concat()、join()、slice() 和 toString() 用于查询数组中的
信息,而不修改数组。concat() 和 slice() 方法返回新数组;而 join() 和 toString() 方
法返回字符串。concat() 方法将新数组和元素列表作为参数,并将其与现有数组结合起来创
建新数组。slice() 方法具有两个名为 startIndex 和 endIndex 的参数,并返回一个新数
组,它包含从现有数组分离出来的元素副本。分离从 startIndex 处的元素开始,到
endIndex 处的前一个元素结束。值得强调的是, endIndex 处的元素不包括在返回值中。
以下示例通过 concat() 和 slice() 方法,使用其它数组的元素创建一个新数组:
var array1:Array = ["alpha", "beta"];
var array2:Array = array1.concat("gamma", "delta");
trace(array2); // 输出:alpha,beta,gamma,delta
var array3:Array = array1.concat(array2);
trace(array3); // 输出:alpha,beta,alpha,beta,gamma,delta
var array4:Array = array3.slice(2,5);
trace(array4); // 输出:alpha,beta,gamma
可以使用 join() 和 toString() 方法查询数组,并将其内容作为字符串返回。如果 join()
方法没有使用参数,则这两个方法的行为相同,它们都返回包含数组中所有元素的列表(以
逗号分隔)的字符串。与 toString() 方法不同,join() 方法接受名为 delimiter 的参数;
可以使用此参数,选择要用作返回字符串中各个元素之间分隔符的符号。
以下示例创建名为 rivers 的数组,并调用 join() 和 toString() 以便按字符串形式返回数
组中的值。toString() 方法用于返回以逗号分隔的值 (riverCSV) ;而 join() 方法用于返
回以 + 字符分隔的值。
var rivers:Array = ["Nile", "Amazon", "Yangtze", "Mississippi"];
var riverCSV:String = rivers.toString();
trace(riverCSV); // 输出:Nile,Amazon,Yangtze,Mississippi
var riverPSV:String = rivers.join("+");
trace(riverPSV); // 输出:Nile+Amazon+Yangtze+Mississippi
对于 join() 方法,应注意的一个问题是,无论为主数组元素指定的分隔符是什么,为嵌套
数组返回的值始终以逗号作为分隔符,如以下示例所示:
var nested:Array = ["b","c","d"];
var letters:Array = ["a",nested,"e"];
var joined:String = letters.join("+");
trace(joined); // 输出:a+b,c,d+e
关联数组199
关联数组
关联数组有时候也称为“哈希”或“映射”,它使用“键”而非数字索引来组织存储的值。
关联数组中的每个键都是用于访问一个存储值的唯一字符串。关联数组为 Object 类的实
例,也就是说每个键都与一个属性名称对应。关联数组是键和值对的无序集合。在代码中,
不应期望关联数组的键按特定的顺序排列。
ActionScript 3.0 中引入了名为“字典”的高级关联数组。字典是 flash.utils 包中 Dictionary
类的实例,使用的键可以为任意数据类型,但通常为 Object 类的实例。换言之,字典的键
不局限于 String 类型的值。
本部分说明如何创建使用字符串作为键的数组以及如何使用 Dictionary 类。
具有字符串键的关联数组
在 ActionScript 3.0 中有两种创建关联数组的方法。第一种方法是使用 Object 构造函数,
它的优点是可以使用对象文本初始化数组。Object 类的实例(也称作“通用对象”)在功
能上等同于关联数组。通用对象的每个属性名称都用作键,提供对存储的值的访问。
以下示例创建一个名为 monitorInfo 的关联数组,并使用对象文本初始化具有两个键和值
对的数组:
var monitorInfo:Object = {type:"Flat Panel", resolution:"1600 x 1200"};
trace(monitorInfo["type"], monitorInfo["resolution"]);
// 输出:Flat Panel 1600 x 1200
如果在声明数组时不需要初始化,可以使用 Object 构造函数创建数组,如下所示:
var monitorInfo:Object = new Object();
使用对象文本或 Object 类构造函数创建数组后,可以使用括号运算符 ([]) 或点运算符 (.)
在数组中添加值。以下示例将两个新值添加到 monitorArray 中:
monitorInfo["aspect ratio"] = "16:10"; // 格式错误,请勿使用空格
monitorInfo.colors = "16.7 million";
trace(monitorInfo["aspect ratio"], monitorInfo.colors);
// 输出:16:10 16.7 million
请注意,名为 aspect ratio 的键包含空格字符。也就是说,空格字符可以与括号运算符一
起使用,但试图与点运算符一起使用时会生成一个错误。不建议在键名称中使用空格。
200 处理数组
第二种关联数组创建方法是使用 Array 构造函数,然后使用括号运算符 ([]) 或点运算符 (.)
将键和值对添加到数组中。如果将关联数组声明为 Array 类型,则将无法使用对象文本初始
化该数组。以下示例使用 Array 构造函数创建一个名为 monitorInfo 的关联数组,并添加
一个名为 type 的键和一个名为 resolution 的键以及它们的值:
var monitorInfo:Array = new Array();
monitorInfo["type"] = "Flat Panel";
monitorInfo["resolution"] = "1600 x 1200";
trace(monitorInfo["type"], monitorInfo["resolution"]);
// 输出: Flat Panel 1600 x 1200
使用 Array 构造函数创建关联数组没有什么优势。即使使用 Array 构造函数或 Array 数据
类型,也不能将 Array 类的 Array.length 属性或任何方法用于关联数组。最好将 Array 构
造函数用于创建索引数组。
具有对象键的关联数组
可以使用 Dictionary 类创建使用对象而非字符串作为键的关联数组。这样的数组有时候也称
作字典、哈希或映射。例如,考虑这样一个应用程序,它可根据 Sprite 对象与特定容器的关
联确定 Sprite 对象的位置。可以使用 Dictionary 对象,将每个 Sprite 对象映射到一个容器。
以下代码创建三个用作 Dictionary 对象的键的 Sprite 对象实例。它为每个键分配了值
GroupA 或 GroupB。值可以是任意数据类型,但在此示例中,GroupA 和 GroupB 均为 Object
类的实例。然后,可以使用属性访问运算符 ([]) 访问与每个键关联的值,如以下代码所示:
import flash.display.Sprite;
import flash.utils.Dictionary;
var groupMap:Dictionary = new Dictionary();
// 要用作键的对象
var spr1:Sprite = new Sprite();
var spr2:Sprite = new Sprite();
var spr3:Sprite = new Sprite();
// 要用作值的对象
var groupA:Object = new Object();
var groupB:Object = new Object();
// 在字典中创建新的键- 值对。
groupMap[spr1] = groupA;
groupMap[spr2] = groupB;
groupMap[spr3] = groupB;
if (groupMap[spr1] == groupA)
{
trace("spr1 is in groupA");
}
关联数组201
if (groupMap[spr2] == groupB)
{
trace("spr2 is in groupB");
}
if (groupMap[spr3] == groupB)
{
trace("spr3 is in groupB");
}
使用对象键循环访问
可以使用 for..in 循环或 for each..in 循环来循环访问 Dictionary 对象的内容。for..in
循环用来基于键进行循环访问;而 for each..in 循环用来基于与每个键关联的值进行循环
访问。
可以使用 for..in 循环直接访问 Dictionary 对象的对象键。还可以使用属性访问运算符
([]) 访问 Dictionary 对象的值。以下代码使用前面的 groupMap 字典示例来说明如何使用
for..in 循环来循环访问 Dictionary 对象:
for (var key:Object in groupMap)
{
trace(key, groupMap[key]);
}
/* 输出:
[object Sprite] [object Object]
[object Sprite] [object Object]
[object Sprite] [object Object]
*/
可以使用 for each..in 循环直接访问 Dictionary 对象的值。以下代码也使用 groupMap 字
典来说明如何使用 for each..in 循环来循环访问 Dictionary 对象:
for each (var item:Object in groupMap)
{
trace(item);
}
/* 输出:
[object Object]
[object Object]
[object Object]
*/
202 处理数组
对象键和内存管理
Adobe Flash Player 使用垃圾回收系统来恢复不再使用的内存。当对象不具有指向它的引用
时,即可对其进行垃圾回收,并会在下次执行垃圾回收系统时恢复内存。例如,以下代码创
建一个新对象,并将对此对象的引用分配给变量 myObject:
var myObject:Object = new Object();
只要有对此对象的引用,垃圾回收系统就不会恢复此对象占用的内存。如果更改 myObject
的值以使其指向其它对象或将其设置为值 null,并且没有对原始对象的其它引用,则可以对
原始对象占用的内存进行垃圾回收。
如果将 myObject 用作 Dictionary 对象中的键,则会创建对原始对象的另一个引用。例如,
以下代码创建两个对象引用(myObject 变量和 myMap 对象中的键):
import flash.utils.Dictionary;
var myObject:Object = new Object();
var myMap:Dictionary = new Dictionary();
myMap[myObject] = "foo";
要使 myObject 引用的对象能够进行垃圾回收,您必须删除对它的所有引用。在此情况下,
必须更改 myObject 的值并从 myMap 中删除 myObject 键,如以下代码所示:
myObject = null;
delete myMap[myObject];
此外,它可以使用 Dictionary 构造函数的 useWeakReference 参数,以使所有字典的键成
为“弱引用”。垃圾回收系统忽略弱引用,也就是说只具有弱引用的对象可以进行垃圾回收。
例如,在以下代码中,要使对象能够进行垃圾回收,您不需要从 myMap 中删除 myObject 键:
import flash.utils.Dictionary;
var myObject:Object = new Object();
var myMap:Dictionary = new Dictionary(true);
myMap[myObject] = "foo";
myObject = null; // 使对象能够进行垃圾回收。
多维数组
多维数组将其它数组作为其元素。例如,考虑一个任务列表,它存储为字符串索引数组:
var tasks:Array = ["wash dishes", "take out trash"];
如果要将一周中每天的任务存储为一个单独的列表,可以创建一个多维数组,一周中的每天
使用一个元素。每个元素包含一个与 tasks 数组类似的索引数组,而该索引数组存储任务列
表。在多维数组中,可以使用任意组合的索引数组和关联数组。以下部分中的示例使用了两
个索引数组或由索引数组组成的关联数组。练习的时候,您也许需要采用其它组合。
多维数组203
两个索引数组
使用两个索引数组时,可以将结果呈现为表或电子表格。第一个数组的元素表示表的行,第
二个数组的元素表示表的列。
例如,以下多维数组使用两个索引数组跟踪一周中每一天的任务列表。第一个数组
masterTaskList 是使用 Array 类构造函数创建的。此数组中的各个元素分别表示一周中的
各天,其中索引 0 表示星期一,索引 6 表示星期日。可将这些元素当成是表的行。可通过
为 masterTaskList 数组中创建的七个元素中的每个元素分配数组文本来创建每一天的任务
列表。这些数组文本表示表的列。
var masterTaskList:Array = new Array();
masterTaskList[0] = ["wash dishes", "take out trash"];
masterTaskList[1] = ["wash dishes", "pay bills"];
masterTaskList[2] = ["wash dishes", "dentist", "wash dog"];
masterTaskList[3] = ["wash dishes"];
masterTaskList[4] = ["wash dishes", "clean house"];
masterTaskList[5] = ["wash dishes", "wash car", "pay rent"];
masterTaskList[6] = ["mow lawn", "fix chair"];
可以使用括号记号访问任意任务列表中的单个项。第一组括号表示一周的某一天,第二组括
号表示这一天的任务列表。例如,要检索星期三的列表中的第二项任务,请首先使用表示星
期三的索引 2,然后使用表示列表中的第二项任务的索引 1。
trace(masterTaskList[2][1]); // 输出:dentist
要检索星期日的任务列表中的第一项,请使用表示星期日的索引 6 和表示列表中的第一项任
务的索引 0。
trace(masterTaskList[6][0]); // 输出:mow lawn
具有索引数组的关联数组
要使单个数组的访问更加方便,可以使用关联数组表示一周的各天并使用索引数组表示任务
列表。通过使用关联数组可以在引用一周中特定的一天时使用点语法,但要访问关联数组的
每个元素还需额外进行运行时处理。以下示例使用关联数组作为任务列表的基础,并使用键
和值对来表示一周中的每一天:
var masterTaskList:Object = new Object();
masterTaskList["Monday"] = ["wash dishes", "take out trash"];
masterTaskList["Tuesday"] = ["wash dishes", "pay bills"];
masterTaskList["Wednesday"] = ["wash dishes", "dentist", "wash dog"];
masterTaskList["Thursday"] = ["wash dishes"];
masterTaskList["Friday"] = ["wash dishes", "clean house"];
masterTaskList["Saturday"] = ["wash dishes", "wash car", "pay rent"];
masterTaskList["Sunday"] = ["mow lawn", "fix chair"];
204 处理数组
点语法通过避免使用多组括号改善了代码的可读性。
trace(masterTaskList.Wednesday[1]); // 输出:dentist
trace(masterTaskList.Sunday[0]); // 输出:mow lawn
可以使用 for..in 循环来循环访问任务列表,但必须使用括号记号来访问与每个键关联的
值,而不是使用点语法。由于 masterTaskList 为关联数组,因而不一定会按照您所期望的
顺序检索元素,如以下示例所示:
for (var day:String in masterTaskList)
{
trace(day + ": " + masterTaskList[day])
}
/* output:
Sunday: mow lawn,fix chair
Wednesday: wash dishes,dentist,wash dog
Friday: wash dishes,clean house
Thursday: wash dishes
Monday: wash dishes,take out trash
Saturday: wash dishes,wash car,pay rent
Tuesday: wash dishes,pay bills
*/
http://hi.baidu.com/andy_tj/blog/item/bacaa3dbcc1cc463d0164e8c.html
【向数组尾端添加元素】
var array:Array = new Array();
array.push("a", "b");
//向数组尾端添加单一元素也可以这样:
array[array.length] = "c";
//如果以索引设定的元素不存在,数组本身会自动扩展以包含足够的元素数目.介于中间的元素会被设为undefined:
array[5] = "e";
trace(array[4]); //输出: undefined
【向数组开端添加元素】
var array:Array = ["a", "b"];
array.unshift("c", "d");
trace(array); //输出: c,d,a,b
【删除数组中第一个元素并返回该元素,使用shift()方法】
var letters:Array = new Array("a", "b", "c");
var firstLetter:String = letters.shift();
trace(letters); //输出: b,c
trace(firstLetter); //输出: a
【删除数组中最后一个元素并返回该元素的值,使用pop()方法】
var letters:Array = new Array("a", "b", "c");
trace(letters); //输出: a,b,c
var letter:String = letters.pop();
trace(letters); //输出: a,b
trace(letter); //输出: c
【删除数组中的元素,给数组添加新元素并返回删除的元素,使用splice()方法】
splice(startIndex:int, deleteCount:uint, ... values):Array
startIndex: 一个整数,它指定数组中开始进行插入或删除的位置处的元素的索引;
deleteCount: 一个整数,它指定要删除的元素数量;
... values: 用逗号分隔的一个或多个值的可选列表或数组,此列表或数组将插入到此数组中由 startIndex 参数指定的位置.
【查找数组中第一个相匹配的元素】
var array:Array = ["a", "b", "c", "d", "a", "b", "c", "d"];
var match:String = "b";
for(var i:int = 0; i < array.length; i++) {
if(array[i] == match) {
trace("Element with index " + i + " found to match " + match);
//输出: Element with index 1 found to match b
break;
}
}
【查找数组中最后一个相匹配的元素】
var array:Array = ["a", "b", "c", "d", "a", "b", "c", "d"];
var match:String = "b";
for(var i:int = array.length - 1; i >= 0; i--) {
if(array[i] == match) {
trace("Element with index " + i + " found to match " + match);
//输出: Element with index 5 found to match b
break;
}
}
【把字符串转成数组】
使用String.split()方法:
var list:String = "I am YoungBoy.";
var words:Array = list.split(" "); //以空格作为分隔符将字符串切割
trace(words); //输出: I,am,YoungBoy.
【把数组转成字符串】
使用String.join()方法:
var myArr:Array = new Array("one", "two", "three");
var myStr:String = myArr.join(" and ");
trace(myArr); //输出: one,two,three
trace(myStr); //输出: one and two and three
【使用对象数组处理相关数据】
var cars:Array = new Array();
cars.push({make:"Mike", year:1997, color:"blue"});
cars.push({make:"Kelly", year:1986, color:"red"});
for(var i:int = 0; i < cars.length; i++) {
trace(cars[i].make + " - " + cars[i].year + " - " + cars[i].color);
}
//输出:
// Mike - 1997 - blue
// Kelly - 1986 - red
【在数组中获取最小或最大值】
var scores:Array = [10, 4, 15, 8];
scores.sort(Array.NUMERIC);
trace("Minimum: " + scores[0]);
trace("Maximum: " + scores[scores.length - 1]);
【使用for ... in语句读取关联数组元素】
var myObject:Object = new Object();
myObject.name = "YoungBoy";
myObject.age = 20;
for(var i:String in myObject) {
trace(i + ": " + myObject[i]);
}
//输出: name: YoungBoy
// age: 20
注意: for ... in循环不会显示对象所有的内建属性.例如,循环会显示执行期间新增的特殊属性,但是,不会列出内建对象的方法,即使都是储存在对象属性内.
常见数组任务
本章介绍了以下常见的数组使用活动:
■ 创建索引数组
■ 添加和删除数组元素
■ 对数组元素进行排序
■ 提取数组的某些部分
■ 处理关联数组和字典
■ 处理多维数组
■ 复制数组元素
■ 创建数组子类
重要概念和术语
以下参考列表包含将会在本章中遇到的重要术语:
■ 数组 (Array):用作容器以将多个对象组合在一起的对象。
■ 关联数组 (Associative array):使用字符串键来标识各个元素的数组。
■ 字典 (Dictionary):其项目由一对对象(称为键和值)组成的数组。它使用键来标识单
个元素,而不是使用数字索引。
■ 元素 (Element):数组中的单个项目。
■ 索引 (Index):用于标识索引数组中的单个元素的数字“地址”。
索引数组191
■ 索引数组 (Indexed array):这是一种标准类型的数组,它将每个元素存储在编号元素中,
并使用数字(索引)来标识各个元素。
■ 键 (Key):用于标识关联数组或字典中的单个元素的字符串或对象。
■ 多维数组 (Multidimensional array):此数组包含的项目是数组,而不是单个值。
索引数组
索引数组存储一系列经过组织的单个或多个值,其中的每个值都可以通过使用一个无符号整
数值进行访问。第一个索引始终是数字 0,且添加到数组中的每个后续元素的索引以 1 为增
量递增。正如以下代码所示,可以调用 Array 类构造函数或使用数组文本初始化数组来创建
索引数组:
// 使用 Array 构造函数。
var myArray:Array = new Array();
myArray.push("one");
myArray.push("two");
myArray.push("three");
trace(myArray); // 输出:one,two,three
// 使用数组文本。
var myArray:Array = ["one", "two", "three"];
trace(myArray); // 输出:one,two,three
Array 类中还包含可用来修改索引数组的属性和方法。这些属性和方法几乎是专用于索引数
组而非关联数组的。
索引数组使用无符号 32 位整数作为索引号。索引数组的最大大小为 232-1,即
4,294,967,295。如果要创建的数组大小超过最大值,则会出现运行时错误。
192 处理数组
数组元素的值可以为任意数据类型。ActionScript 3.0 不支持“指定类型的数组”概念,也
就是说,不能指定数组的所有元素都属于特定数据类型。
本部分说明如何使用 Array 类创建和修改索引数组,首先讲的是如何创建数组。修改数组的
方法分为三类,包括如何插入元素、删除元素和对数组进行排序。最后一类中的方法将现有
数组当作只读数组,这些方法仅用于查询数组。所有查询方法都返回新的数组,而非修改现
有数组。本部分结尾讨论了如何扩展 Array 类。
创建数组
Array 构造函数的使用有三种方式。第一种,如果调用不带参数的构造函数,会得到空数组。
可以使用 Array 类的 length 属性来验证数组是否不包含元素。例如,以下代码调用不带参
数的 Array 构造函数:
var names:Array = new Array();
trace(names.length); // 输出:0
第二种,如果将一个数字用作 Array 构造函数的唯一参数,则会创建长度等于此数值的数
组,并且每个元素的值都设置为 undefined。参数必须为介于值 0 和 4,294,967,295 之间
的无符号整数。例如,以下代码调用带有一个数字参数的 Array 构造函数:
var names:Array = new Array(3);
trace(names.length); // 输出:3
trace(names[0]); // 输出:undefined
trace(names[1]); // 输出:undefined
trace(names[2]); // 输出:undefined
第三种,如果调用构造函数并传递一个元素列表作为参数,将创建具有与每个参数对应的元
素的数组。以下代码将三个参数传递给 Array 构造函数:
var names:Array = new Array("John", "Jane", "David");
trace(names.length); // 输出:3
trace(names[0]); // 输出:John
trace(names[1]); // 输出:Jane
trace(names[2]); // 输出:David
也可以创建具有数组文本或对象文本的数组。可以将数组文本直接分配给数组变量,如以下
示例所示:
var names:Array = ["John", "Jane", "David"];
索引数组193
插入数组元素
可以使用 Array 类的三种方法(push()、unshift() 和 splice())将元素插入数组。push()
方法用于在数组末尾添加一个或多个元素。换言之,使用 push() 方法在数组中插入的最后
一个元素将具有最大索引号。unshift() 方法用于在数组开头插入一个或多个元素,并且始
终在索引号 0 处插入。splice() 方法用于在数组中的指定索引处插入任意数目的项目。
下面的示例对所有三种方法进行了说明。它创建一个名为 planets 的数组,以便按照距离太
阳的远近顺序存储各个行星的名称。首先,调用 push() 方法以添加初始项 Mars。接着,调
用 unshift() 方法在数组开头插入项 Mercury。最后,调用 splice() 方法在 Mercury 之后
和 Mars 之前插入项 Venus 和 Earth。传递给 splice() 的第一个参数是整数 1,它用于指
示从索引 1 处开始插入。传递给 splice() 的第二个参数是整数 0,它表示不应删除任何项。
传递给 splice() 的第三和第四个参数 Venus 和 Earth 为要插入的项。
var planets:Array = new Array();
planets.push("Mars"); // 数组内容:Mars
planets.unshift("Mercury"); // 数组内容:Mercury,Mars
planets.splice(1, 0, "Venus", "Earth");
trace(planets); // 数组内容:Mercury,Venus,Earth,Mars
push() 和 unshift() 方法均返回一个无符号整数,它们表示修改后的数组长度。在用于插
入元素时,splice() 方法返回空数组,这看上去也许有点奇怪,但考虑到 splice() 方法的
多用途性,您便会觉得它更有意义。通过使用 splice() 方法,不仅可以将元素插入到数组
中,而且还可以从数组中删除元素。用于删除元素时,splice() 方法将返回包含被删除元素
的数组。
删除数组元素
可以使用 Array 类的三种方法(pop()、shift() 和 splice())从数组中删除元素。pop()
方法用于从数组末尾删除一个元素。换言之,它将删除位于最大索引号处的元素。shift()
方法用于从数组开头删除一个元素,也就是说,它始终删除索引号 0 处的元素。splice()
方法既可用来插入元素,也可以删除任意数目的元素,其操作的起始位置位于由发送到此方
法的第一个参数指定的索引号处。
以下示例使用所有三种方法从数组中删除元素。它创建一个名为 oceans 的数组,以便存储
较大水域的名称。数组中的某些名称为湖泊的名称而非海洋的名称,因此需要将其删除。
首先,使用 splice() 方法删除项 Aral 和 Superior,并插入项 Atlantic 和 Indian。传递
给 splice() 的第一个参数是整数 2,它表示应从列表中的第三个项(即索引 2 处)开始执
行操作。第二个参数 2 表示应删除两个项。其余两个参数 Atlantic 和 Indian 是要在索引
2 处插入的值。
194 处理数组
然后,使用 pop() 方法删除数组中的最后一个元素 Huron。最后,使用 shift() 方法删除数
组中的第一个项 Victoria。
var oceans:Array = ["Victoria", "Pacific", "Aral", "Superior", "Indian",
"Huron"];
oceans.splice(2, 2, "Arctic", "Atlantic"); // 替换 Aral 和 Superior
oceans.pop(); // 删除 Huron
oceans.shift(); // 删除 Victoria
trace(oceans); // 输出:Pacific,Arctic,Atlantic,Indian
pop() 和 shift() 方法均返回已删除的项。由于数组可以包含任意数据类型的值,因而返回
值的数据类型为 Object。splice() 方法将返回包含被删除值的数组。可以更改 oceans 数
组示例,以使 splice() 调用将此数组分配给新的数组变量,如以下示例所示:
var lakes:Array = oceans.splice(2, 2, "Arctic", "Atlantic");
trace(lakes); // 输出:Aral,Superior
您可能会遇到这样的代码,它在数组元素上使用 delete 运算符。delete 运算符用于将数组
元素的值设置为 undefined,但它不会从数组中删除元素。例如,下面的代码在 oceans 数
组的第三个元素上使用 delete 运算符,但此数组的长度仍然为 5:
var oceans:Array = ["Arctic", "Pacific", "Victoria", "Indian", "Atlantic"];
delete oceans[2];
trace(oceans); // 输出:Arctic,Pacific,,Indian,Atlantic
trace(oceans[2]); // 输出:undefined
trace(oceans.length); // 输出:5
可以使用数组的 length 属性截断数组。如果将数组的 length 属性设置为小于数组当前长
度的值,则会截断数组,在索引号高于 length 的新值减 1 处所存储的任何元素将被删除。
例如,如果 oceans 数组的排序是将所有有效项放在数组的开始处,则可以使用 length 属性
删除数组末尾的项,如以下代码所示:
var oceans:Array = ["Arctic", "Pacific", "Victoria", "Aral", "Superior"];
oceans.length = 2;
trace(oceans); // 输出:Arctic,Pacific
对数组排序
可以使用三种方法(reverse()、sort() 和 sortOn())通过排序或反向排序来更改数组的
顺序。所有这些方法都用来修改现有数组。reverse() 方法用于按照以下方式更改数组的顺
序:最后一个元素变为第一个元素,倒数第二个元素变为第二个元素,依此类推。sort() 方
法可用来按照多种预定义的方式对数组进行排序,甚至可用来创建自定义排序算法。
sortOn() 方法可用来对对象的索引数组进行排序,这些对象具有一个或多个可用作排序键
的公共属性。
索引数组195
reverse() 方法不带参数,也不返回值,但可以将数组从当前顺序切换为相反顺序。以下示
例颠倒了 oceans 数组中列出的海洋顺序:
var oceans:Array = ["Arctic", "Atlantic", "Indian", "Pacific"];
oceans.reverse();
trace(oceans); // 输出:Pacific,Indian,Atlantic,Arctic
sort() 方法按照“默认排序顺序”重新安排数组中的元素。默认排序顺序具有以下特征:
■ 排序区分大小写,也就是说大写字符优先于小写字符。例如,字母 D 优先于字母 b。
■ 排序按照升序进行,也就是说低位字符代码(例如 A)优先于高位字符代码(例如 B)。
■ 排序将相同的值互邻放置,并且不区分顺序。
■ 排序基于字符串,也就是说,在比较元素之前,先将其转换为字符串(例如,10 优先于
3,因为相对于字符串 "3" 而言,字符串 "1" 具有低位字符代码)。
您也许需要不区分大小写或者按照降序对数组进行排序,或者您的数组中包含数字,从而需
要按照数字顺序而非字母顺序进行排序。sort() 方法具有 options 参数,可通过该参数改
变默认排序顺序的各个特征。options 是由 Array 类中的一组静态常量定义的,如以下列表
所示:
■ Array.CASEINSENSITIVE:此选项可使排序不区分大小写。例如,小写字母 b 优先于大
写字母 D。
■ Array.DESCENDING:用于颠倒默认的升序排序。例如,字母 B 优先于字母 A。
■ Array.UNIQUESORT:如果发现两个相同的值,此选项将导致排序中止。
■ Array.NUMERIC:这会导致排序按照数字顺序进行,比方说 3 优先于 10。
以下示例重点说明了这些选项中的某些选项。它创建一个名为 poets 的数组,并使用几种不
同的选项对其进行排序。
var poets:Array = ["Blake", "cummings", "Angelou", "Dante"];
poets.sort(); // 默认排序
trace(poets); // 输出:Angelou,Blake,Dante,cummings
poets.sort(Array.CASEINSENSITIVE);
trace(poets); // 输出:Angelou,Blake,cummings,Dante
poets.sort(Array.DESCENDING);
trace(poets); // 输出:cummings,Dante,Blake,Angelou
poets.sort(Array.DESCENDING | Array.CASEINSENSITIVE); // 使用两个选项
trace(poets); // 输出:Dante,cummings,Blake,Angelou
196 处理数组
您也可以编写自定义排序函数,然后将其作为参数传递给 sort() 方法。例如,如果有一个
名称列表,其中每个列表元素都包含一个人的全名,但现在要按照姓来对列表排序,则必须
使用自定义排序函数解析每个元素,然后使用排序函数中的姓。以下代码说明如何使用作为
参数传递给 Array.sort() 方法的自定义函数来完成上述工作:
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); // 输出:John Q. Smith,Jane Doe,Mike Jones
names.sort(orderLastName);
trace(names); // 输出:Jane Doe,Mike Jones,John Q. Smith
自定义排序函数 orderLastName() 使用正则表达式从每个元素中提取姓,以用于比较操作。
针对 names 数组调用 sort() 方法时,函数标识符 orderLastName 用作唯一的参数。排序函
数接受两个参数 a 和 b,因为它每次对两个数组元素进行操作。排序函数的返回值指示应如
何对元素排序:
■ 返回值 -1 表示第一个参数 a 优先于第二个参数 b。
■ 返回值 1 表示第二个参数 b 优先于第一个参数 a。
■ 返回值为 0 表示元素具有相同的排序优先级。
sortOn() 方法是为具有包含对象的元素的索引数组设计的。这些对象应至少具有一个可用
作排序键的公共属性。如果将 sortOn() 方法用于任何其它类型的数组,则会产生意外结果。
以下示例修改 poets 数组,以使每个元素均为对象而非字符串。每个对象既包含诗人的姓又
包含诗人的出生年份。
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"});
索引数组197
可以使用 sortOn() 方法,按照 born 属性对数组进行排序。sortOn() 方法定义两个参数
fieldName 和 options。必须将 fieldName 参数指定为字符串。在以下示例中,使用两个参
数 "born" 和 Array.NUMERIC 来调用 sortOn()。Array.NUMERIC 参数用于确保按照数字顺
序进行排序,而不是按照字母顺序。即使所有数字具有相同的数位,这也是一种很好的做法,
因为当后来在数组中添加较少数位或较多数位的数字时,它会确保排序如期继续进行。
poets.sortOn("born", Array.NUMERIC);
for (var i:int = 0; i < poets.length; ++i)
{
trace(poets[i].name, poets[i].born);
}
/* 输出:
Wang 701
Dante 1265
Blake 1757
cummings 1894
Angelou 1928
*/
通常,sort() 和 sortOn() 方法用来修改数组。如果要对数组排序而又不修改现有数组,请将
Array.RETURNINDEXEDARRAY 常量作为 options 参数的一部分进行传递。此选项将指示方法返
回反映排序的新数组同时保留原始数组原封不动。方法返回的数组为由反映新排序顺序的索引
号组成的简单数组,不包含原始数组的任何元素。例如,如果要根据出生年份对 poets 数组排
序,同时不对数组进行修改,请在传递的 options 参数中包括 Array.RETURNINDEXEDARRAY
常量。
以下示例将返回的索引信息存储在名为 indices 的数组中,然后使用 indices 数组和未修
改的 poets 数组按出生年份输出诗人:
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);
}
/* 输出:
Wang 701
Dante 1265
Blake 1757
cummings 1894
Angelou 1928
*/
198 处理数组
查询数组
Array 类中的其余四种方法 concat()、join()、slice() 和 toString() 用于查询数组中的
信息,而不修改数组。concat() 和 slice() 方法返回新数组;而 join() 和 toString() 方
法返回字符串。concat() 方法将新数组和元素列表作为参数,并将其与现有数组结合起来创
建新数组。slice() 方法具有两个名为 startIndex 和 endIndex 的参数,并返回一个新数
组,它包含从现有数组分离出来的元素副本。分离从 startIndex 处的元素开始,到
endIndex 处的前一个元素结束。值得强调的是, endIndex 处的元素不包括在返回值中。
以下示例通过 concat() 和 slice() 方法,使用其它数组的元素创建一个新数组:
var array1:Array = ["alpha", "beta"];
var array2:Array = array1.concat("gamma", "delta");
trace(array2); // 输出:alpha,beta,gamma,delta
var array3:Array = array1.concat(array2);
trace(array3); // 输出:alpha,beta,alpha,beta,gamma,delta
var array4:Array = array3.slice(2,5);
trace(array4); // 输出:alpha,beta,gamma
可以使用 join() 和 toString() 方法查询数组,并将其内容作为字符串返回。如果 join()
方法没有使用参数,则这两个方法的行为相同,它们都返回包含数组中所有元素的列表(以
逗号分隔)的字符串。与 toString() 方法不同,join() 方法接受名为 delimiter 的参数;
可以使用此参数,选择要用作返回字符串中各个元素之间分隔符的符号。
以下示例创建名为 rivers 的数组,并调用 join() 和 toString() 以便按字符串形式返回数
组中的值。toString() 方法用于返回以逗号分隔的值 (riverCSV) ;而 join() 方法用于返
回以 + 字符分隔的值。
var rivers:Array = ["Nile", "Amazon", "Yangtze", "Mississippi"];
var riverCSV:String = rivers.toString();
trace(riverCSV); // 输出:Nile,Amazon,Yangtze,Mississippi
var riverPSV:String = rivers.join("+");
trace(riverPSV); // 输出:Nile+Amazon+Yangtze+Mississippi
对于 join() 方法,应注意的一个问题是,无论为主数组元素指定的分隔符是什么,为嵌套
数组返回的值始终以逗号作为分隔符,如以下示例所示:
var nested:Array = ["b","c","d"];
var letters:Array = ["a",nested,"e"];
var joined:String = letters.join("+");
trace(joined); // 输出:a+b,c,d+e
关联数组199
关联数组
关联数组有时候也称为“哈希”或“映射”,它使用“键”而非数字索引来组织存储的值。
关联数组中的每个键都是用于访问一个存储值的唯一字符串。关联数组为 Object 类的实
例,也就是说每个键都与一个属性名称对应。关联数组是键和值对的无序集合。在代码中,
不应期望关联数组的键按特定的顺序排列。
ActionScript 3.0 中引入了名为“字典”的高级关联数组。字典是 flash.utils 包中 Dictionary
类的实例,使用的键可以为任意数据类型,但通常为 Object 类的实例。换言之,字典的键
不局限于 String 类型的值。
本部分说明如何创建使用字符串作为键的数组以及如何使用 Dictionary 类。
具有字符串键的关联数组
在 ActionScript 3.0 中有两种创建关联数组的方法。第一种方法是使用 Object 构造函数,
它的优点是可以使用对象文本初始化数组。Object 类的实例(也称作“通用对象”)在功
能上等同于关联数组。通用对象的每个属性名称都用作键,提供对存储的值的访问。
以下示例创建一个名为 monitorInfo 的关联数组,并使用对象文本初始化具有两个键和值
对的数组:
var monitorInfo:Object = {type:"Flat Panel", resolution:"1600 x 1200"};
trace(monitorInfo["type"], monitorInfo["resolution"]);
// 输出:Flat Panel 1600 x 1200
如果在声明数组时不需要初始化,可以使用 Object 构造函数创建数组,如下所示:
var monitorInfo:Object = new Object();
使用对象文本或 Object 类构造函数创建数组后,可以使用括号运算符 ([]) 或点运算符 (.)
在数组中添加值。以下示例将两个新值添加到 monitorArray 中:
monitorInfo["aspect ratio"] = "16:10"; // 格式错误,请勿使用空格
monitorInfo.colors = "16.7 million";
trace(monitorInfo["aspect ratio"], monitorInfo.colors);
// 输出:16:10 16.7 million
请注意,名为 aspect ratio 的键包含空格字符。也就是说,空格字符可以与括号运算符一
起使用,但试图与点运算符一起使用时会生成一个错误。不建议在键名称中使用空格。
200 处理数组
第二种关联数组创建方法是使用 Array 构造函数,然后使用括号运算符 ([]) 或点运算符 (.)
将键和值对添加到数组中。如果将关联数组声明为 Array 类型,则将无法使用对象文本初始
化该数组。以下示例使用 Array 构造函数创建一个名为 monitorInfo 的关联数组,并添加
一个名为 type 的键和一个名为 resolution 的键以及它们的值:
var monitorInfo:Array = new Array();
monitorInfo["type"] = "Flat Panel";
monitorInfo["resolution"] = "1600 x 1200";
trace(monitorInfo["type"], monitorInfo["resolution"]);
// 输出: Flat Panel 1600 x 1200
使用 Array 构造函数创建关联数组没有什么优势。即使使用 Array 构造函数或 Array 数据
类型,也不能将 Array 类的 Array.length 属性或任何方法用于关联数组。最好将 Array 构
造函数用于创建索引数组。
具有对象键的关联数组
可以使用 Dictionary 类创建使用对象而非字符串作为键的关联数组。这样的数组有时候也称
作字典、哈希或映射。例如,考虑这样一个应用程序,它可根据 Sprite 对象与特定容器的关
联确定 Sprite 对象的位置。可以使用 Dictionary 对象,将每个 Sprite 对象映射到一个容器。
以下代码创建三个用作 Dictionary 对象的键的 Sprite 对象实例。它为每个键分配了值
GroupA 或 GroupB。值可以是任意数据类型,但在此示例中,GroupA 和 GroupB 均为 Object
类的实例。然后,可以使用属性访问运算符 ([]) 访问与每个键关联的值,如以下代码所示:
import flash.display.Sprite;
import flash.utils.Dictionary;
var groupMap:Dictionary = new Dictionary();
// 要用作键的对象
var spr1:Sprite = new Sprite();
var spr2:Sprite = new Sprite();
var spr3:Sprite = new Sprite();
// 要用作值的对象
var groupA:Object = new Object();
var groupB:Object = new Object();
// 在字典中创建新的键- 值对。
groupMap[spr1] = groupA;
groupMap[spr2] = groupB;
groupMap[spr3] = groupB;
if (groupMap[spr1] == groupA)
{
trace("spr1 is in groupA");
}
关联数组201
if (groupMap[spr2] == groupB)
{
trace("spr2 is in groupB");
}
if (groupMap[spr3] == groupB)
{
trace("spr3 is in groupB");
}
使用对象键循环访问
可以使用 for..in 循环或 for each..in 循环来循环访问 Dictionary 对象的内容。for..in
循环用来基于键进行循环访问;而 for each..in 循环用来基于与每个键关联的值进行循环
访问。
可以使用 for..in 循环直接访问 Dictionary 对象的对象键。还可以使用属性访问运算符
([]) 访问 Dictionary 对象的值。以下代码使用前面的 groupMap 字典示例来说明如何使用
for..in 循环来循环访问 Dictionary 对象:
for (var key:Object in groupMap)
{
trace(key, groupMap[key]);
}
/* 输出:
[object Sprite] [object Object]
[object Sprite] [object Object]
[object Sprite] [object Object]
*/
可以使用 for each..in 循环直接访问 Dictionary 对象的值。以下代码也使用 groupMap 字
典来说明如何使用 for each..in 循环来循环访问 Dictionary 对象:
for each (var item:Object in groupMap)
{
trace(item);
}
/* 输出:
[object Object]
[object Object]
[object Object]
*/
202 处理数组
对象键和内存管理
Adobe Flash Player 使用垃圾回收系统来恢复不再使用的内存。当对象不具有指向它的引用
时,即可对其进行垃圾回收,并会在下次执行垃圾回收系统时恢复内存。例如,以下代码创
建一个新对象,并将对此对象的引用分配给变量 myObject:
var myObject:Object = new Object();
只要有对此对象的引用,垃圾回收系统就不会恢复此对象占用的内存。如果更改 myObject
的值以使其指向其它对象或将其设置为值 null,并且没有对原始对象的其它引用,则可以对
原始对象占用的内存进行垃圾回收。
如果将 myObject 用作 Dictionary 对象中的键,则会创建对原始对象的另一个引用。例如,
以下代码创建两个对象引用(myObject 变量和 myMap 对象中的键):
import flash.utils.Dictionary;
var myObject:Object = new Object();
var myMap:Dictionary = new Dictionary();
myMap[myObject] = "foo";
要使 myObject 引用的对象能够进行垃圾回收,您必须删除对它的所有引用。在此情况下,
必须更改 myObject 的值并从 myMap 中删除 myObject 键,如以下代码所示:
myObject = null;
delete myMap[myObject];
此外,它可以使用 Dictionary 构造函数的 useWeakReference 参数,以使所有字典的键成
为“弱引用”。垃圾回收系统忽略弱引用,也就是说只具有弱引用的对象可以进行垃圾回收。
例如,在以下代码中,要使对象能够进行垃圾回收,您不需要从 myMap 中删除 myObject 键:
import flash.utils.Dictionary;
var myObject:Object = new Object();
var myMap:Dictionary = new Dictionary(true);
myMap[myObject] = "foo";
myObject = null; // 使对象能够进行垃圾回收。
多维数组
多维数组将其它数组作为其元素。例如,考虑一个任务列表,它存储为字符串索引数组:
var tasks:Array = ["wash dishes", "take out trash"];
如果要将一周中每天的任务存储为一个单独的列表,可以创建一个多维数组,一周中的每天
使用一个元素。每个元素包含一个与 tasks 数组类似的索引数组,而该索引数组存储任务列
表。在多维数组中,可以使用任意组合的索引数组和关联数组。以下部分中的示例使用了两
个索引数组或由索引数组组成的关联数组。练习的时候,您也许需要采用其它组合。
多维数组203
两个索引数组
使用两个索引数组时,可以将结果呈现为表或电子表格。第一个数组的元素表示表的行,第
二个数组的元素表示表的列。
例如,以下多维数组使用两个索引数组跟踪一周中每一天的任务列表。第一个数组
masterTaskList 是使用 Array 类构造函数创建的。此数组中的各个元素分别表示一周中的
各天,其中索引 0 表示星期一,索引 6 表示星期日。可将这些元素当成是表的行。可通过
为 masterTaskList 数组中创建的七个元素中的每个元素分配数组文本来创建每一天的任务
列表。这些数组文本表示表的列。
var masterTaskList:Array = new Array();
masterTaskList[0] = ["wash dishes", "take out trash"];
masterTaskList[1] = ["wash dishes", "pay bills"];
masterTaskList[2] = ["wash dishes", "dentist", "wash dog"];
masterTaskList[3] = ["wash dishes"];
masterTaskList[4] = ["wash dishes", "clean house"];
masterTaskList[5] = ["wash dishes", "wash car", "pay rent"];
masterTaskList[6] = ["mow lawn", "fix chair"];
可以使用括号记号访问任意任务列表中的单个项。第一组括号表示一周的某一天,第二组括
号表示这一天的任务列表。例如,要检索星期三的列表中的第二项任务,请首先使用表示星
期三的索引 2,然后使用表示列表中的第二项任务的索引 1。
trace(masterTaskList[2][1]); // 输出:dentist
要检索星期日的任务列表中的第一项,请使用表示星期日的索引 6 和表示列表中的第一项任
务的索引 0。
trace(masterTaskList[6][0]); // 输出:mow lawn
具有索引数组的关联数组
要使单个数组的访问更加方便,可以使用关联数组表示一周的各天并使用索引数组表示任务
列表。通过使用关联数组可以在引用一周中特定的一天时使用点语法,但要访问关联数组的
每个元素还需额外进行运行时处理。以下示例使用关联数组作为任务列表的基础,并使用键
和值对来表示一周中的每一天:
var masterTaskList:Object = new Object();
masterTaskList["Monday"] = ["wash dishes", "take out trash"];
masterTaskList["Tuesday"] = ["wash dishes", "pay bills"];
masterTaskList["Wednesday"] = ["wash dishes", "dentist", "wash dog"];
masterTaskList["Thursday"] = ["wash dishes"];
masterTaskList["Friday"] = ["wash dishes", "clean house"];
masterTaskList["Saturday"] = ["wash dishes", "wash car", "pay rent"];
masterTaskList["Sunday"] = ["mow lawn", "fix chair"];
204 处理数组
点语法通过避免使用多组括号改善了代码的可读性。
trace(masterTaskList.Wednesday[1]); // 输出:dentist
trace(masterTaskList.Sunday[0]); // 输出:mow lawn
可以使用 for..in 循环来循环访问任务列表,但必须使用括号记号来访问与每个键关联的
值,而不是使用点语法。由于 masterTaskList 为关联数组,因而不一定会按照您所期望的
顺序检索元素,如以下示例所示:
for (var day:String in masterTaskList)
{
trace(day + ": " + masterTaskList[day])
}
/* output:
Sunday: mow lawn,fix chair
Wednesday: wash dishes,dentist,wash dog
Friday: wash dishes,clean house
Thursday: wash dishes
Monday: wash dishes,take out trash
Saturday: wash dishes,wash car,pay rent
Tuesday: wash dishes,pay bills
*/