您的位置:首页 > 其它

第五章 数组

2007-07-13 13:02 29 查看
介绍:数组是编写强大ActionScript程序基础。
数组提供了把一组相关的数据联系起来的功能,并且具有管理和处理数据的能力。数组队我们来说并不是有多么的难以理解,在我们平时生活中经常接触类是的东西。比如我们可以把一组食品的列表当作数组,人们的住址名册包含名字,地址,出生日期等等。图书馆是用索引系统来管理图书,概念上来说,每本书就是图书馆数组的一个元素。
在ActionScript中有两种类型的数组,以整数位下标的数组和关联数组。第一种数组中的每个元素都有一个唯一的下标,下标从零开始,每一个数据元素占用一个数据插槽。这种类型的数组为你提供顺序访问数组的便利。第二种是关联数组,关联数组是一些键值对,后边我们会详细的讨论。
注意:一般情况我们使用整数下标的数组多,所有在本章提到array指的就是这种数组
在我们开始之前我们必须知道如何来创建一个数组,在ActionScript中有两种创建数组的方式,一种是使用array()类的构造器,另外的一种是使用字面量来创建。使用构造器创建数组可以有三种不同的方式:
//创建一个空的数组
var array:Array = new Array();
//创建一个包含未定义元素的数组,elements为数组的长度
var array:Array = new Array(elements);
//创建一个指定了特定元素的数组
var array:Array = new Array(element0,...elementN);
我们也可以通过字面量来创建数组:
var letters:Array = ["a", "b", "c"];
我们可以通过下标来给数组赋值或者取出数组中的值:
[align=left]// Set the fifth element of the array called items to "apples" [/align]
[align=left]// (array indexes start at 0).[/align]
[align=left]items[4] = "apples";[/align]
[align=left]// Display the fifth element in the Output window.[/align]
trace(items[4]); // Displays: apples
在数组Array类的方法中,有些方法会改变原始的数组的值,而有些则会返回一个新的数组。ActionScript不考虑你给数组中存储什么样的数据类型,你可以存储任何数据类型,比如strings,boole,number,references type等。你也可以在一个数组中存储多种不同类型的数据:
var data:Array = ["a", 2, true, new Object()];并且不象其他的语言,ActionScript的数组在声明的时候可以不用指定长度。
给数组的开始或者结束赋值
问题:你想向已经声明好的数组中添加元素
解决:使用push()方法给数组的末尾赋值,使用unshift()方法给数组的开头赋值。
讨论:使用push方法来从数组的末尾开始赋值,可以传递一个或者多个参数到这个方法,这个方法会顺序的把这些元素添加到数组中:
[align=left]var array:Array = new Array();[/align]
array.push("val 1", "val 2");
现在数组里的元素是[“val 1”,“val 2”]。你也可以使用数组的下标来给数组的某个元素赋值,由于ActionScript的数组是0数组,也就是数第一个元素的下标是零而不是1,所以数组的最后一个的元素是array[array.length-1]而不是array[array.lengthj]。如果你使用后一个赋值的话会给数组增加一个元素。如果你设定数组的下标不存在,即大于目前数组的最大的下标array.leng-1,那么系统会自动扩展数组来满足指定的下标,在指定的下标和之前的最大下标之间的元素都初始化为undefined。比如我们有一个三个元素的数组[“a”,“b”,“c”]letters,当我们给第五个元素赋值的时候,数组变成["a", "b", "c", undefined, undefined, "f"]。
给数组增加元素是很平常的,当你想保存之前的一些历史纪录的时候,你就必须这样做。
使用方法unshift在数组的开头增加元素。数组把所有存在的元素的下标向后移动一位,然后把新的元素添到下标0。
[align=left]// Create an array with four elements:[/align]
[align=left]// "a", "b", "c", and "d".[/align]
[align=left]var letters:Array = new Array( );[/align]
[align=left]letters.push("a", "b", "c", "d");[/align]
[align=left]// Add "z" to the beginning of the array. This shifts all [/align]
[align=left]// the other elements so the value of "a" moves from [/align]
[align=left]// index 0 to index 1, etc.[/align]
[align=left]letters.unshift("z");[/align]
[align=left]// Display the results by looping through the elements. [/align]
[align=left]// See Recipe 5.2.[/align]
[align=left]for (var i:int = 0; i < letters.length; i++) {[/align]
[align=left] trace(letters[i]);[/align]
}
我们应该把元素添加在数组的开头还是结尾?一般取决于你如何使用数组。
遍历数组的元素
问题:我们想读取数组中的每个元素
解决:是用for循环
讨论:是用for循环,因为数组的最后一个元素的下标是array.length-1,因此我们可以通过如下循环来遍历数组的元素:
[align=left]var letters:Array = ["a", "b", "c"];[/align]
[align=left]for (var i:int = 0; i < letters.length; i++) {[/align]
[align=left] // Display the elements in the Output panel.[/align]
[align=left] trace("Element " + i + ": " + letters[i]);[/align]
}
当然你也可以逆序的遍历数组。为了稍微有一些性能上的提升,我们可以在循环的外部来计算数组的长度,而不用每次去计算数组的长度。但是这有个前提条件,也就是说我们在遍历的过程中不能修改修改数组的元素个数,比如增加或者删除,如果你在循环数组的时候有这样的需求,那每次去计算数组的长度就比较合适。
在数组中找匹配的元素
问题:你想在一个数组中找第一个匹配某个值得元素
解决:是用for循环,或者是用下载的代码中的ArrayUtilities类的findMatchIndex()方法和findLastMatchIndex()方法,或者findMatchIndices()方法。
讨论:在使用for循环的时候,当找到匹配的元素的时候使用break来跳出循环,以节省运行时间。使用我们提供的类ArrayUtilities类会更加的方便,这个类有三个用来寻找某个元素的方法,findMatchIndex(),findLastMatchIndex()和findMatchIndices()。FindMatchIndex()最少需要两个参数,第一个是数组,第二个是一个需要匹配的值,例子:
[align=left]var letters:Array = ["a", "b", "c", "d"];[/align]
[align=left]trace(ArrayUtilities.findMatchIndex(letters, "b"));[/align]
[align=left]// Displays: 1[/align]
[align=left]trace(ArrayUtilities.findMatchIndex(letters, "r"));[/align]
// Displays: -1
这个方法找到匹配的值返回第一个匹配的元素的下标,如果找不到,返回-1。
如果你想从某一个位置开始寻找匹配的元素的下标,传递第三个参数为起始下标,如果你想做模糊匹配(即如果某个字符串包含你的值就匹配),那么第三个参数传递为true。如果你既想从某一个下标开始,也想做模糊匹配,那么第三个参数设置为true,而第四个参数为你要开始的下标,例子:
//从某一个位置开始匹配
[align=left]var letters:Array = ["a", "b", "c", "d", "a", "b", "c", "d"];[/align]
[align=left]trace(ArrayUtilities.findMatchIndex(letters, "a", 1));[/align]
// Displays: 4
//模糊匹配
var words:Array = ["bicycle", "baseball", "mat", "board"];

trace(ArrayUtilities.findMatchIndex(words, "s", true));

// Displays: 1

FindLastMatchIndex()和findMatchIndex()方的使用基本一样,唯一不同的是这个方法是从数组的末尾开始最匹配。
最后方法findMatchIndices()的使用和前两个方法一样,这个方法返回一个匹配元素的下标的数组:
[align=left]var words:Array = ["bicycle", "baseball", "mat", "board"];[/align]
[align=left]trace(ArrayUtilities.findMatchIndices(words, "b", true));[/align]
// Displays: 0,1,3
从数组中删除元素
问题:你想从一个数组中删除一个或几个元素并且让剩余的元素填充这些空的下标
解决:splice()方法从数组的中间删除一个元素,pop()从数组的末尾删除,shift()从数组的开头删除。
讨论:从数组的中间删除一个元素是用splice()方法,这个方法需要两个参数。第一个是start,这个参数表示你想从那个下标开始删除,第二个参数deleteCount,删除元素的个数。如果你指定的位置无效,那么开始参数之后的所有的元素都回被删除。Splice方法会返回一个包含被删除元素的数组:
[align=left]var letters:Array = ["a", "b", "c", "d"];[/align]
[align=left]// Remove two elements from letters starting at index 0.[/align]
var deleted:Array = letters.splice(0, 2);
如果要从数组的开头或者结尾删除一个元素的话,是用pop()和shift(),这两个反法也会返回被删除的元素:
[align=left]var letters:Array = ["a", "b", "c", "d"]; [/align]
[align=left]// Remove the first element and display its value.[/align]
[align=left]trace(letters.shift( ));[/align]
[align=left]// Remove the last element and display its value.[/align]
[align=left]trace(letters.pop( )); [/align]
[align=left]// Display the remaining elements. [/align]
[align=left]// The array has two elements left: "b" and "c".[/align]
[align=left]for (var i = 0; i < letters.length; i++) {[/align]
[align=left]trace(letters[i]);[/align]
}
如果你想通过for循环来删除一个数组中的某些元素,千万不要忘记在删除了之后修改对应的下标:
[align=left]var numbers:Array = new Array(4, 10);[/align]
[align=left]numbers[4] = 1;[/align]
[align=left]trace(numbers); // Displays: 4,10,undefined,undefined,1[/align]
[align=left]for(var i:int = 0; i < numbers.length; i++) {[/align]
[align=left] if(numbers[i] == undefined) {[/align]
[align=left] numbers.splice(i, 1);[/align]
[align=left] i--;[/align]
[align=left] }[/align]
[align=left]}[/align]
trace(numbers); // Displays: 4,10,1
向数组中间中插入元素
问题:向数组中插入几个元素
解决:是用splice()方法
讨论:splice方法不但可以从数组总删除数据,也可以给数组中插入数据。传递给这个方法的第一个和第二个参数之后的参数将被插入到数组中,具体插入到第一个参数制定的位置之后。如果给第二个参数传递一个0的话,没有元素会被删除,并且新的元素会被加入到数组中:
[align=left]var letters:Array = ["a", "b", "c", "d"];[/align]
[align=left]// Insert three string values ("one", "two", and "three")[/align]
[align=left]// starting at index 1.[/align]
[align=left]letters.splice(1, 0, "r", "s", "t");[/align]
[align=left]// letters now contains seven elements:[/align]
[align=left]// "a", "r", "s", "t", "b", "c", and "d".[/align]
[align=left]for (var i:int = 0; i < letters.length; i++) {[/align]
[align=left]trace(letters[i]);[/align]
}
你也可以删除元素之后同时在插入一些元素:
var letters:Array = ["a", "b", "c", "d"];

// Remove two elements and insert three more

// into letters starting at index 1.

letters.splice(1, 2, "r", "s", "t");

// myArray now contains five elements:

// "a", "r", "s", "t", and "d".

for (var i:int = 0; i < letters.length; i++) {

trace(letters[i]);

}

把字符串转换成数组
问题:你想把一些字符串的列表转换成一个数组
解决:是用String.split()方法
讨论:split方法可以以一定的分隔符号把一个字符串转换成数组,被转换的字符串必须有一定的可分隔的格式。比如susan,robert,palua这个字符串的规律就是以逗号分隔。
Split方法必须接受两个参数:第一个参数是用来分隔字符串的标示字符,如果没有指定的话那么所有的字符串都会放到返回的数组的第一个元素中去。第二个参数limit表示要把多少个元素放到返回的数组中去,如果不指定的话,那么默认的所有的元素都会被放到返回的数组中去。
[align=left]var list:String = "Peter Piper picked a peck of pickled peppers";[/align]
[align=left]// Split the string using the space as the delimiter. This puts [/align]
[align=left]// each word into an element of the new array, words.[/align]
var words:Array = list.split(" ");
把数组转换成字符串
问题:把数组转换成字符串
解决:是用join()方法
讨论:ActionScript内建了对数组向字符串转换的支持,当然数组每个元素不论是字符串类型还是其他的类型,都会被相应的转换成字符串。使用join()方法可以把一个数组转换成字符串。Join方法可以接受一个参数,用来标示如何来把数组的每个元素分开,再字符串中,例如:
[align=left]var letters:Array = ["a", "b", "c"];[/align]
trace(letters.join("|")); // Displays: a|b|c
如果你不使用分隔符号,那逗号就是默认的分隔符号:
[align=left]var letters:Array = ["a", "b", "c"];[/align]
trace(letters.join()); // Displays: a,b,c
注意:toString()方法和没有参数的join方法有同样的效果。事实上,如果你在一个需要字符串参数的地方使用数组,系统会自动调用toString()方法。
拷贝一个数组来产生一个新的数组
问题:我们想精确的拷贝一个数组,而且这个新的数组不是对原始数组的引用
解决:使用concat()和slice()方法。可选的,你可以使用ArrayUtilities.duplicate()方法来拷贝一个数组。
讨论:数组是一种复杂的数据类型,我们不能通过象拷贝原始类型那样来拷贝数组,说白了,数组是引用类型。所以很多情况下对数组的复制都只是拷贝了指向内存的某个地方的一个指针,而没有真正的复制数组。如果我们确实要拷贝一个数组到另外一个新的变量里边去,是用concat()方法:
[align=left]// Assign elements of an array.[/align]
[align=left]var letters:Array = ["a", "b", "c"];[/align]
[align=left]// Create an independent copy of letters using concat( ),[/align]
[align=left]// which returns a new array.[/align]
[align=left]var newLetters:Array = letters.concat( ); [/align]
[align=left]// Both arrays contain the same values, as expected.[/align]
[align=left]trace(letters); // Displays: "a,b,c"[/align]
[align=left]trace(newLetters); // Displays: "a,b,c"[/align]
[align=left]// Change letters' value.[/align]
[align=left]letters = ["d", "e", "f"];[/align]
[align=left]// Unlike preceding examples, the arrays are independent.[/align]
[align=left]trace(letters); // Displays: "d,e,f"[/align]
trace(newLetters); // Displays: "a,b,c"
当然我们也可以使用var newLetters:Array = letters.slice(0)方法来复制数组。
一般情况下,上边的两个方法在一维数组中使用没有什么问题,但是如果是多维的数组,那么这两个方法就不会很好的工作了。如果是关联数组,没有concat和slice方法,如果是多维的数组,concat和slice方法只能复制最高层次的一个数组,而不能复制内嵌的数组,下边的例子说明了这个道理:
[align=left]var coordinates:Array = new Array( );[/align]
[align=left]coordinates.push([0,1,2,3]);[/align]
[align=left]coordinates.push([4,5,6,7]);[/align]
[align=left]coordinates.push([8,9,10,11]);[/align]
[align=left]coordinates.push([12,13,14,15]);[/align]
[align=left]// Make a duplicate.[/align]
[align=left]var coordinatesDuplicate:Array = coordinates.concat( );[/align]
[align=left]// Replace one of the elements of one of the nested arrays[/align]
[align=left]// in the duplicate.[/align]
[align=left]coordinatesDuplicate[0][0] = 20;[/align]
[align=left]trace(coordinates[0][0]); // Displays: 20[/align]
[align=left]// Replace one of the top-level elements.[/align]
[align=left]coordinatesDuplicate[1] = [21,22,23,24];[/align]
trace(coordinates[1]); // Displays: 4,5,6,7
如果我们想精确的复制一个数组,必须使用递归的方式来复制。ArrayUtilities.duplicate()方法为我们作了这件事情,让我们可以很轻松的来复制一个多维的数组,duplicate()方法只接受一个参数,就是要被复制的数组的引用,然后duplicate方法返回一个复制的数组。默认的duplicate方法的行为和concate和slice同样,如果我们想精确的复制一个数组,就必须指定第二个参数,把第二个参数设置为true就表示我们想精确的复制一个数组,例如:
[align=left]// Create a two-dimensional array.[/align]
[align=left]var coordinates:Array = new Array( );[/align]
[align=left]for(var i:int = 0; i < 4; i++) {[/align]
[align=left] coordinates[i] = new Array( );[/align]
[align=left] for(var j:int = 0; j < 4; j++) {[/align]
[align=left] coordinates[i].push(String(i) + "," + String(j));[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left]// Duplicate coordinates. Cast the result as an array.[/align]
[align=left]var newCoordinates:Array = ArrayUtilities.duplicate(coordinates, true) as Array;[/align]
[align=left]// Replace an element in the nested array.[/align]
[align=left]newCoordinates[0][0] = "a";[/align]
[align=left]// Use the toString() method of the ArrayUtilities class [/align]
[align=left]// to quickly output the contents of the arrays.[/align]
[align=left]trace(ArrayUtilities.toString(coordinates));[/align]
trace(ArrayUtilities.toString(newCoordinates));
下边的例子是关联数组的复制:
[align=left]var coordinatesMap:Object = new Object( );[/align]
[align=left]coordinatesMap.a = [{a: 1},{b: 2}, {c: 3}, {d: 4}];[/align]
[align=left]coordinatesMap.b = [{a: 1},{b: 2}, {c: 3}, {d: 4}];[/align]
[align=left]coordinatesMap.c = [{a: 1},{b: 2}, {c: 3}, {d: 4}];[/align]
[align=left]coordinatesMap.d = [{a: 1},{b: 2}, {c: 3}, {d: 4}];[/align]
[align=left]var newCoordinatesMap:Object = ArrayUtilities.duplicate(coordinatesMap, true);[/align]
[align=left]newCoordinatesMap.a[0] = {r: 5};[/align]
[align=left]trace(ArrayUtilities.toString(coordinatesMap));[/align]
trace(ArrayUtilities.toString(newCoordinatesMap));
存储复杂的多维数据
问题:如何来存储几组在每个位置上相关的数据,来方便访问
解决:是用parallel 数组,或者多维数组,或者数组对象(array of object)
讨论:我们可以创建几个平行的数组来保存这些在每个位置相关的数据。例如,我们将在第七章看到的beginGradientFill()方法使用三个平行的数组,他们是color,alphas,和ratios。在这三个数组中,每个对应的index上的数据都是相关的。
如何创建平行数组,我们可以通过创建多个相关的数组,例子:
[align=left]var colors:Array = ["maroon", "beige", "blue", "gray"];[/align]
[align=left]var years:Array = [1997, 2000, 1985, 1983];[/align]
[align=left]var makes:Array = ["Honda", "Chrysler", "Mercedes", "Fiat"];[/align]
[align=left]// Loop through the arrays. Since each array is the same [/align]
[align=left]// length, you can use the length property of any of them [/align]
[align=left]// in the for statement. Here, we use makes.length.[/align]
[align=left]for (var i:int = 0; i < makes.length; i++) {[/align]
[align=left] // Displays:[/align]
[align=left] // A maroon 1997 Honda[/align]
[align=left] // A beige 2000 Chrysler[/align]
[align=left] // A blue 1985 Mercedes[/align]
[align=left] // A gray 1983 Fiat[/align]
[align=left] // Display the elements with corresponding indexes [/align]
[align=left] // from the arrays.[/align]
[align=left] trace("A " + colors[i] + " " + years[i] + " " + makes[i]);[/align]
}
另外的一个选择就是创建多维数组:
[align=left]// Create an array, cars, and populate it with elements that [/align]
[align=left]// are arrays. Each element array represents a car and [/align]
[align=left]// contains three elements (color, year, and make).[/align]
[align=left]var cars:Array = new Array();[/align]
[align=left]cars.push(["maroon", 1997, "Honda"]);[/align]
[align=left]cars.push(["beige", 2000, "Chrysler"]);[/align]
[align=left]cars.push(["blue", 1985, "Mercedes"]);[/align]
[align=left]cars.push(["gray", 1983, "Fiat"]);[/align]
[align=left]// Loop through the elements of the cars array.[/align]
[align=left]for (var i:int = 0; i < cars.length; i++) {[/align]
[align=left] // The output is the same as in the [/align]
[align=left] // earlier parallel arrays example:[/align]
[align=left] // A maroon 1997 Honda[/align]
[align=left] // A beige 2000 Chrysler[/align]
[align=left] // A blue 1985 Mercedes[/align]
[align=left] // A gray 1983 Fiat[/align]
[align=left] // Output each element of each subarray, cars[i]. [/align]
[align=left] // Note the use of two successive indexes in brackets, [/align]
[align=left] // such as cars[i][0].[/align]
[align=left] TRace("A " + cars[i][0] + " " + [/align]
[align=left] cars[i][1] + " " + [/align]
最后一种选择就是使用array object,这种技术和前边的多维数组差不多,但是它比多维数组有更大灵活性,当我们使用多为数组的时候,我们使用下标来引用数组的元素。但是通过array object我们为每个元素指定名字,而不用去使用index来访问:
[align=left]// Create an array, cars, and populate it with objects.[/align]
[align=left]// Each object has a make property, a year property, [/align]
[align=left]// and a color property.[/align]
[align=left]var cars:Array = new Array();[/align]
[align=left]// Here, object literals are used to define three properties[/align]
[align=left]// for each car; the object literals are added to [/align]
[align=left]// the main array.[/align]
[align=left]cars.push({make: "Honda", year: 1997, color: "maroon"});[/align]
[align=left]cars.push({make: "Chrysler", year: 2000, color: "beige"});[/align]
[align=left]cars.push({make: "Mercedes", year: 1985, color: "blue"});[/align]
[align=left]cars.push({make: "Fiat", year: 1983, color: "gray"}); [/align]
[align=left]// Loop through the cars array.[/align]
[align=left]for (var i:int = 0; i < cars.length; i++) {[/align]
[align=left] // The output is the same as in the earlier examples,[/align]
[align=left] // but each value is referenced by its property name,[/align]
[align=left] // which is more programmer-friendly.[/align]
[align=left] trace("A " + cars[i].color + " " + cars[i].year + " " + cars[i].make);[/align]
}
给数组排序
问题:给一个给定的数组排序
解决:是用sort方法,对array object,可以使用sortOn()方法
讨论:想对一个数组进行简单的排序,使用sort方法就可以,不用传递任何参数,就会对数组中的元素按照字符表来排序。
var words:Array = ["tricycle", "relative", "aardvark", "jargon"];

[align=left]words.sort( );[/align]
trace(words); // Displays: aardvark,jargon,relative,tricycle
sort方法也可以接受一些参数,来订制我们需要排序的方式,并且sort方式是大小写敏感的,大写字符会被排在小写字母之前。但是你可以通过设置参数Array.CASEINSENSITIVE来改变默认的设置。
[align=left]var words:Array = ["Tricycle", "relative", "aardvark", "jargon"];[/align]
[align=left]words.sort(Array.CASEINSENSITIVE);[/align]
trace(words); // Displays: aardvark,jargon,relative,Tricycle
当我们对数字排序的时候,默认的数字的排序是根据数字的ascill码来进行,但是我们也可以改变默认的设置,通过设置Array.NUMERICK可以改变默认的设置。
[align=left]var scores:Array = [10, 2, 14, 5, 8, 20, 19, 6];[/align]
[align=left]scores.sort( );[/align]
trace(scores); // Displays: 10,14,19,2,20,5,6,8
改变后:
[align=left]var scores:Array = [10, 2, 14, 5, 8, 20, 19, 6];[/align]
[align=left]scores.sort(Array.NUMERIC);[/align]
trace(scores); // Displays: 2,5,6,8,10,14,19,20
还有两个我们可以在sort方法中使用的常量Array.UNIQUESORT和Array.RETURNUBDEXEDARRAY。在一些情况下我们想在数组的元素的值都是唯一值得情况才对它进行排序,那我们就可以使用Array.UNIQUESORT参数,Flash只有在数组的值都是唯一值得时候才对数组进行排序。否则,属足返回零,并不对原始的数组作任何的改变。还有些时候我们不想改变原始的数组的顺序,而对数组作一定的排序来返回一个排序好的数组,那我们就可以使用Array.RETURNINDEXEDARRAY参数,这个参数会使sort方法返回一个新的数组,这个数组就是以前数组排序好的数组,元素和下表还原数组统一:
[align=left]var words:Array = ["tricycle", "relative", "aardvark", "jargon"];[/align]
[align=left]var indices:Array = words.sort(Array.RETURNINDEXEDARRAY);[/align]
[align=left]trace(words); // Displays: tricycle,relative,aardvark,jargon[/align]
[align=left]trace(indices); // Displays: 2,3,1,0[/align]
[align=left]for(var i:int = 0; i < words.length; i++) {[/align]
[align=left] /* Displays:[/align]
[align=left] aardvark[/align]
[align=left] jargon[/align]
[align=left] relative[/align]
[align=left] tricycle[/align]
[align=left] */[/align]
[align=left] trace(words[indices[i]]);[/align]
}
当然我们也可以给sort方法传递不只一个的参数来进行排序,多个参数之间是用 | 符号来分隔:
[align=left]var words:Array = ["Tricycle", "relative", "aardvark", "jargon"];[/align]
[align=left]words.sort(Array.CASEINSENSITIVE | Array.DESCENDING);[/align]
trace(words); // Displays: Tricycle,relative,jargon,aardvark
前边讨论的都是如何来给一些字符串数组或者数字数字来排序,如果数组中是对象的话,那我们如何来排序呢?可以使用sortOn()方法,这个方法接受一个参数用来表示用那个属性来对元素进行排序:
[align=left]var cars:Array = new Array();[/align]
[align=left]cars.push({make: "Honda", year: 1997, color: "maroon"});[/align]
[align=left]cars.push({make: "Chrysler", year: 2000, color: "beige"});[/align]
[align=left]cars.push({make: "Mercedes", year: 1985, color: "blue"});[/align]
[align=left]cars.push({make: "Fiat", year: 1983, color: "gray"});[/align]
[align=left]// Sort the cars array according to the year property [/align]
[align=left]// of each element.cars.sortOn("year");[/align]
[align=left]for (var i:int = 0; i < cars.length; i++) {[/align]
[align=left] /* Displays:[/align]
[align=left] gray 1983 Fiat[/align]
[align=left] blue 1985 Mercedes[/align]
[align=left] maroon 1997 Honda[/align]
[align=left] beige 2000 Chrysler[/align]
[align=left] */[/align]
[align=left] trace(cars[i].color + "/t" + [/align]
[align=left] cars[i].year + "/t" + [/align]
[align=left] cars[i].make);[/align]
}
SortOn方法也可以接受多个字段来对某个一个数组排序,数组被指定的这些字段按顺序来排序,为了理解这个原理,看下边的例子:
[align=left]var cars:Array = new Array( );[/align]
[align=left]cars.push({make: "Honda", year: 1997, color: "maroon"});[/align]
[align=left]cars.push({make: "Chrysler", year: 2000, color: "beige"});[/align]
[align=left]cars.push({make: "Mercedes", year: 1985, color: "blue"});[/align]
[align=left]cars.push({make: "Fiat", year: 1983, color: "gray"});[/align]
[align=left]cars.push({make: "Honda", year: 1992, color: "silver"});[/align]
[align=left]cars.push({make: "Chrysler", year: 1968, color: "gold"});[/align]
[align=left]cars.push({make: "Mercedes", year: 1975, color: "green"});[/align]
[align=left]cars.push({make: "Fiat", year: 1983, color: "black"});[/align]
[align=left]cars.push({make: "Honda", year: 2001, color: "blue"});[/align]
[align=left]cars.push({make: "Chrysler", year: 2004, color: "orange"});[/align]
[align=left]cars.push({make: "Mercedes", year: 2000, color: "white"});[/align]
[align=left]cars.push({make: "Fiat", year: 1975, color: "yellow"});[/align]
[align=left]// Sort the cars array according to the year property [/align]
[align=left]// of each element, then by the make.[/align]
[align=left]cars.sortOn(["year", "make"]);[/align]
[align=left]for (var i:int = 0; i < cars.length; i++) {[/align]
[align=left] /* Displays:[/align]
[align=left] gold 1968 Chrysler[/align]
[align=left] yellow 1975 Fiat[/align]
[align=left] green 1975 Mercedes[/align]
[align=left] black 1983 Fiat[/align]
[align=left] gray 1983 Fiat[/align]
[align=left] blue 1985 Mercedes[/align]
[align=left] silver 1992 Honda[/align]
[align=left] maroon 1997 Honda[/align]
[align=left] beige 2000 Chrysler[/align]
[align=left] white 2000 Mercedes[/align]
[align=left] blue 2001 Honda[/align]
[align=left] orange 2004 Chrysler[/align]
[align=left] */[/align]
[align=left] trace(cars[i].color + "/t" + [/align]
[align=left] cars[i].year + "/t" + [/align]
[align=left] cars[i].make);[/align]
}
这个例子中我们的方法先使用year来排序,然后使用make来排序。SortOn方法也可以接受排序修饰符,我们可以传递Array.DESCENDING等参数到这个方法:
[align=left]cars.sortOn("year", Array.DESCENDING);[/align]
[align=left] [/align]
[align=left]for (var i:int = 0; i < cars.length; i++) {[/align]
[align=left] /* Displays:[/align]
[align=left] beige 2000 Chrysler[/align]
[align=left] maroon 1997 Honda[/align]
[align=left] blue 1985 Mercedes[/align]
[align=left] gray 1983 Fiat[/align]
[align=left] */[/align]
[align=left] trace(cars[i].color + "/t" + [/align]
[align=left] cars[i].year + "/t" + [/align]
[align=left] cars[i].make);[/align]
}
有时候我们也需要对一个数组进行反转,是用Array类提供的reverse()方法。我们在使用sort和sortOn方法的时候如果不指定Array.RETURNINDEXEDARRAY修饰符的话,默认的所有多数组的排序都是在原始的数组上进行。
执行用户自定义排序
问题:你可能需要更为复杂的排序策略
解决:是用sort方法并且给它传递一个排序的方法
讨论:如果我们传递一个方法到sort函数,这个方法就不会不断的比较数组里的两个元素的值,根据返回的结果是正数,负数和零来判定比较的两个元素的大小关系。返回0现在的元素关系不发生变化,这个 方法会不断地执行直到数组中的元素都很有序为止。使用用户自定函数要比听起来简单,你不用考虑的太复杂,因为你只需要比较两个元素的大小关系就可以了。
下边的一个例子是我们需要对一些乐队的字符串进行排序,默认的sort方法会用第一个单词The类对几个以The开头的字符串排序,我们定义一个简单排序函数:
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;

}

}

这里没有对自定义比较函数的复杂度作任何约束,你可以定义任意复杂的比较函数,但是有一点要注意的是这个函数会被调用很多很多次,所以如果你的比较函数定义的过于复杂会对性能有一些影响,所以我们建议不要那样做。
使数组的元素随机化
问题:想使一个数组的元素随机排列
解决:给sort方法传递一个比较函数,这个函数随机的返回0或者1
讨论:在一些游戏中,比如纸牌游戏,我们需要洗牌,所以有的时候必须对数组中的元素来随即的重新的排列,我们可以用给sort方法传递一个能产生随即的0和1的函数来达到这个目的,这个函数的定义如下:
[align=left]function randomSort(elementA:Object, elementB:Object):Number {[/align]
[align=left] return Math.random( ) - .5[/align]
}
上边这个值得返回在-0.5到0.5之间,所以当返回负数的时候我们交换两个比较元素的位置,为正数的时候保持不变。我们可以使用这个函数:
var numbers:Array = new Array( );

for(var i:int=0;i<20;i++) {

numbers[i] = i;

}

numbers.sort(randomSort);

for(var i:int=0;i<numbers.length;i++) {

trace(numbers[i]);

}

获得数组最大何最小元素
问题:获得数组中最大和最小的元素
解决:我们先对数组排序,然后取出第一个,和最后一个元素
讨论:非常的简单,只要对数组进行适当的排序:
var scores:Array = [10, 4, 15, 8];

[align=left]scores.sort(Array.NUMERIC);[/align]
[align=left]trace("Minimum: " + scores[0]);[/align]
trace("Maximum: " + scores[scores.length - 1]);
比较数组
问题:向判断两个数组是不是有相同的元素
解决:遍历连个数组的每个元素然后比较
讨论:前面我们分析过,数组是引用类型,如果我们用等值符号来判断两个数组是不是相等,只是在他们的同一性,即他们是不是引用到相同的一块内存地址。如果我们要判断两个数组是不是有相同的元素,第一种方法是使用循环来遍历连个数组:
var equivalent:Boolean = true;

for(var i:int = 0; i < letters1.length; i++) {

if(letters1[i] != letters2[i]) {

equivalent = false;

break;

}

}

另外本书提供的代码中的类ArrayUtilities有个方法equals可以做同样的事情。这个方法接受两个参数,分别是待比较的两个数组,这个方法返回一个bool类型的值来表示两个数组是不是有相同的元素:
[align=left]var letters1:Array = ["a", "b", "c", "d"];[/align]
[align=left]var letters2:Array = ["a", "b", "c", "d"];[/align]
[align=left]trace(ArrayUtilities.equals(letters1, letters2));[/align]
// Displays: true
我们在比较连个数组的时候是根据每个数组对应位置的元素来比较的,有时候我们可能不去考虑数组每个具体位置的数据的关系,而只是简单的判断他们是不是包含有完全相同的元素的时候,我们可以给equals方法传第三个参数,这是一个bool类型的值来表示是不是要忽略顺序:
[align=left]var letters1:Array = ["a", "b", "c", "d"];[/align]
[align=left]var letters2:Array = ["b", "a", "d", "c"];[/align]
[align=left]trace(ArrayUtilities.equals(letters1, letters2));[/align]
[align=left]// Displays: false[/align]
[align=left]trace(ArrayUtilities.equals(letters1, letters2, true));[/align]
// Displays: true
下边看看equals方法的定义:
public static function equals(arrayA:Array,

arrayB:Array,

bNotOrdered:Boolean):Boolean {

// If the two arrays don't have the same number of elements,

// they obviously are not equivalent.

if(arrayA.length != arrayB.length) {

return false;

}

// Create a copy of each so that anything done to the copies

// doesn't affect the originals.

var arrayACopy:Array = arrayA.concat( );

var arrayBCopy:Array = arrayB.concat( );

// If the order of the elements of the two arrays doesn't

// matter, sort the two copies so the order of the copies

// matches when comparing.

if(bNotOrdered) {

arrayACopy.sort( );

arrayBCopy.sort( );

}

// Loop through each element of the arrays, and compare them.

// If they don't match, delete the copies and return false.

for(var i:int = 0; i < arrayACopy.length; i++) {

if(arrayACopy[i] != arrayBCopy[i]) {

delete arrayACopy;

delete arrayBCopy;

    return false;

}

}

// Otherwise the arrays are equivalent.

// So delete the copies and return true.

delete arrayACopy;

delete arrayBCopy;

return true;

}

创建关联数组
问题:我们想创建一个能通过名字而不是数字下标来访问的数组
解决:创建关联数组
讨论:关联数组提供了一半数组不能比拟的优势,它可以通过名字来访问数组的内容。关联数组在其它的一些语言中称为hash表,在ActionScript中,关联数组是Object类的实例。关联数组是键值对的集合,我们可以功过键来访问相应的值。键可以使用很有表示意思的字符串组成。
你可以通过对对象字面量来声明关联数组,使用这种方法的时候,使用{ } 来把一些用逗号分隔开的键值对包括起来,键和值之间用 :来分隔,例如:
[align=left]var memebers:Object = {scribe: "Franklin", chairperson: "Gina", treasurer: "Sindhu"};[/align]
[align=left] 你也可以使用object对象的构造器来声明关联数组,这样可以增加可读性,并且你可以添加很多不同的键和值到关联数组中:[/align]
[align=left]var members:Object = new Object( );[/align]
[align=left]members.scribe = "Franklin";[/align]
[align=left]members.chairperson = "Gina";[/align]
[align=left]members.treasurer = "Sindhu";[/align]
[align=left] 当然我们也可以声明一个空的关联数组:var members:Object={ };。[/align]
[align=left] 关联数组的读取有两种方法,一种是通过属性来读取:[/align]
[align=left]trace(members.scribe); // Displays: Franklin[/align]
[align=left] 还有一种方法就是如同读取一半数组那样方法关联数组的元素:[/align]
[align=left]trace(members["scribe"]); // Displays: Franklin[/align]
[align=left] 当然我们不仅仅通过这连个方法来读取数组的元素,我们也可以通过这两个方法来给关联数组的元素赋值。[/align]
[align=left]var members:Object = new Object( );[/align]
[align=left]members["councilperson"] = "Ruthie";[/align]
[align=left]trace(members.councilperson); // Displays: Ruthie[/align]
[align=left]members.councilperson = "Rebecca";[/align]
[align=left]trace(members["councilperson"]); // Displays: Rebecca[/align]
[align=left]读取关联数组的所有的元素[/align]
[align=left]问题:我们想循环读取关联数组的元素的值[/align]
[align=left] 解决:使用for..in循环[/align]
[align=left] 讨论:我们通过使用for..in来遍历关联数组的元素,关联数组的元素不能通过数字下标来访问,并且关联数组中的元素的是没有顺序的。因此关联数组没有reverse方法和sort方法,或者改变它的元素的顺利之类的方法。[/align]
[align=left] 幸运的是,你可以通过for...in循环来遍历关联数组的元素:[/align]
[align=left]for (key in object) {[/align]
[align=left] // Actions[/align]
[align=left]}[/align]
[align=left] For..in循环不需要显式的循环数字,因为元素的个数已经固定。Key用来保存每次你循环遍历的键的名字,而不是某一个特定的键的名字。Objec就是你需要进行遍历的数组,例子:[/align]
[align=left]var members:Object = new Object( );[/align]
[align=left]members.scribe = "Franklin";[/align]
[align=left]members.chairperson = "Gina";[/align]
[align=left]members.treasurer = "Sindhu";[/align]
[align=left]// Use a for . . . in statement to loop through all elements.[/align]
[align=left]for (var sRole:String in members) {[/align]
[align=left] // Displays:[/align]
[align=left] // treasurer: Sindhu[/align]
[align=left] // chairperson: Gina[/align]
[align=left] // scribe: Franklin[/align]
[align=left] trace(sRole + ": " + members[sRole]);[/align]
[align=left]}[/align]
[align=left] For..in方法只遍历object对象中的用户添加的元素,而不会遍历到内建的一些对象。[/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: