Array 是存儲值列表的主要類型,提供最簡單的方法來添加和提取其中的值。Haxe 數組的多數語法和 Java、ActionScript 中的很相似,所以開發者如果了解這些語言,可以快速的閱讀本節,了解一些主要的區別。
Haxe 中使用 Array 之前,必須先實例化,除非你使用字面值初始化 Array 列表。對于本章目的,只需要使用 `new Array() ` 賦值到 Array 類型變量即可:
~~~
var myArray : Array < Int > = new Array();
~~~
不需要在實例化的時候重新制定包含的數據類型,事實上,任何添加到第二個 Array 關鍵字的類型標識符都會被丟棄。
可以通過重新實例化它來清空一個數組的數據。然而,為了關聯改變一個數組里數據類型,一個新的數組對象需要被聲明并實例化。
一旦實例化了Array對象,可以使用數據進行填充和使用它們。表顯示了操作Array的一些可用方法:
|數組字段|描述|
| -- | -- |
|length: Int|返回當前項的數量。length 是一個只讀屬性|
|concat(a: Array<T>): Array<T>|連接一個數組到當前數組對象的尾部,不改變原數組,返回一個新的數組|
|copy():Array<T>|返回一個新的數組結構,包含相同的布局和數據|
|insert(pos: Int, x:T): Void|添加數據到數組的任何位置|
|iterator(): Iterator<Null<T>>|返回數組值的一個迭代器|
|join(sep: String): String|返回一個字符串,包含了通過一個指定分隔符連接的所有數組項|
|pop():Null<T>|刪除原數組最后一個元素并返回該元素,直接在原數組操作|
|push(x:T):Int|添加指定的項到數組結尾并返回它的位置,直接在原數組操作|
|remove(x:T):Bool|移除第一次出現的指定匹配項,返回一個布爾值結果,成功為true,未找到項為false|
|shitf(): Null<T>|刪除數組中第一個項,并返回它,操作原數組|
|slice(pos: Int, ?end: Int):Array<T>|拷貝指定范圍的數組,返回一個新的數組|
|sort(f:T->T->Int): Void|根據指定的比對函數排序數組,函數如果x==y則返回0,x>y則返回值大于0,x<y則返回值小于0|
|splice(pos: Int, len: Int):Array<T>|移除指定范圍的項,返回它們為一個新的數組|
|toString(): String|返回數組的字符串表現形式|
|unshift(x:T):Void|添加指定的項到數組開始|
`T` 類型本身不是一個類型,但是是一個占位符,代表在運行時決定類型,以符合強類型,當剩下的任何你希望傳入函數的匿名結構。T 類型在以后詳加介紹。
# 從Array中添加或者移除項
* * * * *
有很多方式添加和移除項。每個方法提供某個特定角度的操作。從開始,從尾部,或者數組的任意位置。如果你知道項的定位,可以指定這個位置直接修改為任何變量。通過 索引操作符([])實現這個:
~~~
myArray[3] = 44;
var myInt = myArray[3];
~~~
這里,索引位置為3,代表Array里第4個項,設置其值為 44, 然后同樣的值傳遞到變量 myInt。 當然,如果第4個項已經包含一個你不想覆蓋的值這會是一個問題。這種情況,可以使用Array的lenght屬性,它會返回數組的長度:
~~~
var numItemsInArray : Int = myArray.length;
myArray[numItemsInArray] = 44;
~~~
數組中的項從0開始,Array的lenght是數組下一個可用的空間。這就是說,不論指定多長,使用length屬性作為新的索引永遠不會覆蓋存在的值。
# Pushing 和 popping值
* * * * *
另一個方式執行相同的技巧是使用 push 方法。這個方法確保添加到Array中的值只會附加到Array的尾部。
~~~
var lastLocation : Int = myArray.push(44);
~~~
push 方法返回最后添加的值的位置,可以使用來操作該值。同樣的方式,可以使用 pop 方法移除最后一個項:
~~~
var poppedValue : Int = myArray.pop();
~~~
一旦刪除最后一個項,方法會放回被刪除的值而不是忽略它。以備你可能需要對他進行某種處理。
# Shifting 和 Unshifting 值
* * * * *
Haxe數組也提供一個手段來添加值到Array的頭部,可以使用 unshift方法:
~~~
myArray.unshift(44);
~~~
unshift 方法和push 方法表現方式相同,除了返回 Void ,而不是返回位置之外。這是因為新增的項索引總是為0。當添加值到Array 的開頭,所有其他的值會下移一個順序,所以添加之前第一項的索引會變成 1 。
相似的 pop 方法用來移除數據,返回Array頭部的數據:
~~~
var shiftedValue : Int = myArray.shift();
~~~
# 從Array中間添加或者移除數據
* * * * *
兩個主要的方法用于從Array中間移除數據分別是 remove 和splice 。兩個方法都執行項的移除,但是以不同的方式,都非常有用。
## remove()
remove 方法用來尋找并刪除一個項,通過制定的值。這個方法只接受一個參數,匹配的將被刪除的值。從Array的開始起,這個方法搜索指定的值,當它找到了,搜索便會停止,值將被刪除,使所有的它之后的項提升1個位置:
~~~
var isFound : Bool = myArray.remove(4);
~~~
remove 方法如果刪除成功則返回 true,如果沒有匹配則返回false。因此,它可以用來重復搜索,如果需要,直到返回 false ,所有指定的值都會被刪除。
## Splice()
splice 方法可以移除多個項。splice 接受兩個參數,開始位置和要移除的項的數量:
~~~
var chunk : Array < Int > = myArray.splice(2,2);
~~~
一旦移除成功,一塊的項會被返回,你可以存儲它到一個新的Array,如果你希望的話。
還可以指定開始位置從尾部開始,使用一個負數。這種情況, -1 表示最后一個項,而遞減的往回數Array的項列表:
~~~
var chunk : Array < Int > = myArray.splice(-2,2);
~~~
這里,最后兩個項被移除然后存儲到Array變量 chunk 。
## 使用insert()插入值
插入一個值到Array的中間可以使用簡單的 insert 方法。 insert 接受兩個參數,添加值得為之,和希望插入的值。一旦插入了之,所有存在的在其之后的項位置都會后移1 個:
~~~
myArray.insert(4, someValue);
~~~
# 拷貝和連接數組
* * * * *
數組是對象,并不是Haxe的基礎類型 list 。所以,從一個變量傳遞一個 Array 到另一個不會創建一個數組的副本,僅僅是創建兩個變量,然后指向相同的內存信息。這意味著修改一個Array會自動的修改另一個Array。現在并不需要太深入理解,因為這是其他章節的話題,但是需要說的是,如果你希望復制一個Array的結構到另一個新的Array,需要一些幫助。幸好Haxe提供了一些工具來做這件事,使用 slice 和copy 封裝。
## slice()
slice 方法接受兩個參數,返回Array的一個塊,看起來工作方式和 splice 非常接近。不得不承認經常混淆 slice 和splice之間的用法。兩者聽起來都像血淋林的恐怖電影(切割),如果使用 splice 表示你保護Array中的數據將其留下。
兩者之間有一個差別,然而如果有時錯誤的時候可能會拋出一個編譯器的錯誤,但至少會讓你明白二者的差別。splice 需要 第二個參數指定你要拷貝的塊的結尾位置。這個終點位置不包含在拷貝塊之內。
像 splice一樣,你可以使用一個負數作為開始位置,但是也可食用一個負數作為塊的結尾。記住,開始位置必須在結束為止之前出現:
~~~
var arrayCpy : Array < Int > = myArray.slice(-4,-2);
~~~
## copy()
copy 方法應用到整個數組,創建一個精確的副本,不需要參數:
~~~
var arrayCpy : Array < Int > = myArray.copy();
~~~
警告一下, copy 和slice 方法不會創建重復的數據。因此,如果你的原數組包含對象,拷貝Array的數據會包含這些對象的引用,而不是副本。
現在你可以拷貝Array,怎么拷貝一個Array到另外一個數組的尾部?這操作叫做連接,可以使用 concat 方法對Array進行連接。
## concat()
concat 方法拷貝指定Array的結構到調用方法的Array。要連接的數組的項不會重復,但是通過引用傳遞,所以這不是一個問題,如果只是基礎類型如 Int 或者 String :
~~~
myArray.concat(newArray);
~~~
# 多維數組
* * * * *
多維數組,提供Haxe里非常有用的功能。聽起來就像矩陣,多維數組可以幫助我們處理數組的組,或者數組的組的組,可以想象這個。
要更好的理解多維數組,想象它們用于數字。例如,一千包含十個一百,一百包含十個十,十包含是個單位。可以將其作為Array格式,通過放置每四個數值組之一到 Arrays,就像這樣:
~~~
var thousandths : Array < Int > = [0,1,2,3,4,5,6,7,8,9];
var hundredths : Array < Int > = [0,1,2,3,4,5,6,7,8,9];
var tens : Array < Int > = [0,1,2,3,4,5,6,7,8,9];
var units : Array < Int > = [0,1,2,3,4,5,6,7,8,9];
~~~
這個方法的問題是組保存在每個數組并沒有連接起來。你只有每個Array類型之一,理論上講,應該有是個千位數組,一百個百位數組,一千個十位數組,一萬個個位數組。更多的是,每個數組需要關聯到父數組的關聯項。
要解決這個問題,可以創建數組的數組,通過指定父數組的類型為數組,然后依次重復這個操作為每個層次:
~~~
var numbers : Array < Array < Array < Array < Int > > > > ;
~~~
一旦這樣做,你需要實例化每個數組的層次結構:
~~~
numbers = new Array();
for ( a = 0...9 )
{
numbers[a] = new Array();
for ( b = 0...9 )
{
numbers[a][b] = new Array();
for ( c = 0...9 )
{
numbers[a][b][c] = new Array();
for ( d = 0...9 )
numbers[a][b][c][d] = ( a * 1000 ) + ( b * 100 ) + ( c * 10 ) + d;
}
}
}
~~~
這回繼續下去直到實例化完所有的層次結構中的數字,雖然你可以有選擇的做這些,而不是所有都在前面。一旦這樣做了,你可以訪問數組通過提供一個index操作符的對來訪問數組:
~~~
var thousands : Int = 6;
var hundreds : Int = 4;
var tens : Int = 7;
var units : Int = 3;
numbers[thousands][hundreds][tens][units] = 6473;
~~~
或者:
~~~
numbers[6][4][7][3] = 6473;
~~~
理論上說,一個多維數組可以有許多盡可能大的尺寸,然而很少使用同時超過2維的數組。
- 本書目錄
- 第一章:Haxe介紹
- 互聯網開發的一個問題
- Haxe是什么,為什么產生
- Haxe編譯工具
- Haxe語言
- Haxe如何工作
- 那么Neko是什么
- Haxe和Neko的必須條件
- 本章摘要
- 第二章:安裝、使用Haxe和Neko
- 安裝Haxe
- 使用Haxe安裝程序
- 在Windows上手動安裝Haxe
- Linux上手動安裝Haxe
- 安裝Neko
- Windows上手動安裝Neko
- 在Linux上安裝Neko
- Hello world! 一式三份
- 編譯你的第一個Haxe應用
- 你的程序如何編譯
- HXML編譯文件
- 編譯到Neko
- 編譯為JavaScript
- 程序結構
- 編譯工具開關
- 本章摘要
- 第三章:基礎知識學習
- Haxe層級結構
- 標準數據類型
- 變量
- 類型推斷
- 常數變量
- 簡單的值類型
- 浮點類型
- 整型
- 選擇數值類型
- 布爾類型
- 字符串類型
- 抽象類型
- Void 和 Null
- 動態類型
- unknown類型
- 使用untyped繞過靜態類型
- 注釋代碼
- 轉換數據類型
- Haxe數組
- Array
- List
- Map
- Haxe中使用日期時間
- 創建一個時間對象
- Date組件
- DateTools類
- 操作數據
- 操作符
- Math類
- 使用String函數
- 本章摘要
- 第四章:信息流控制
- 數據存放之外
- 條件語句
- if語句
- switch語句
- 從條件語句返回值
- 循環
- while循環
- for循環
- 循環集合
- Break和Continue
- 函數
- 類的函數
- 局部函數
- Lambda類
- 本章摘要
- 第五章:深入面向對象編程
- 類和對象
- 實例字段
- 靜態字段
- 理解繼承
- Super
- 函數重載
- 構造器重載
- toString()
- 抽象類和抽象方法
- 靜態字段,實例變量和繼承
- 繼承規則
- 使用接口
- 高級類和對象特性
- 類的實現
- 類型參數
- 匿名對象
- 實現動態
- Typedef
- 擴展
- 枚舉
- 構造器參數
- 本章摘要
- 第六章:組織你的代碼
- 編寫可重用代碼
- 使用包
- 聲明一個包
- 隱式導入
- 顯式導入
- 枚舉和包
- 類型查找順序
- 導入一個完整的包
- 導入庫
- Haxe標準庫
- Haxelib庫
- 其他項目中的庫
- 外部庫
- 使用資源
- 文檔化代碼
- 離線文檔
- 在線文檔
- 單元測試
- haxe.unit包
- 編寫測試
- 本章摘要
- 第七章:錯誤調試
- trace函數
- trace輸出
- haxe的trace和ActionScript的trace
- 異常
- 異常處理
- CallStack和ExceptionStack
- 異常管理類
- 創建完全的異常處理類
- 異常類代碼
- 本章摘要
- 第八章:跨平臺工具
- XML
- XML剖析
- Haxe XML API
- 正則表達式
- EReg類
- 模式
- 定時器
- 延遲動作
- 隊列動作
- MD5
- 本章摘要
- 第九章:使用Haxe構建網站
- Web開發介紹
- Web 服務器
- 使用Web服務器發布內容
- HTML速成課程
- Haxe和HTML的區別
- NekoTools Web Server
- Apache安裝mod_neko
- Windows安裝Apache和mod_neko
- Linux安裝Apache和Mod_Neko
- 第一個Haxe網站
- 使用Neko作為網頁Controller
- neko.Web類
- Neko作為前端控制器
- 本章摘要
- 第十章:使用模板進行分離式設計
- 什么是模板
- Template類
- Template語法
- 使用資產
- 何時在模板中使用代碼
- 服務器端模板的Templo
- 安裝Templo
- 使用Templo
- haxe.Template和mtwin.Templo表達式上的區別
- Attr表達式
- Raw表達式
- 邏輯表達式
- 循環表達式
- set, fill, 和 use表達式
- Templo中使用宏
- 手動編譯模版
- 第十一章:執行服務端技巧
- 第十二章:使用Flash構建交互內容
- 第十三章:使用IDE
- 第十四章:通過JavaScript制作更多交互內容
- 第十五章:通過Haxe遠程通信連接所學
- 第十六章:Haxe高級話題
- 第十七章:Neko開發桌面應用
- 第十八章:用SWHX開發桌面Flash
- 第十九章:多媒體和Neko
- 第二十章:使用C/C++擴展Haxe
- 附加部分