集合
集合的定義
Swift中提供了兩種數據結構用於存放數據的集合,各自是數組(Array)和字典(Dictionary)。
他們的主要差別在於數組中的元素由下標確定。而字典中的數據的值由數據的鍵(Key)決定。下面我們覺得集合就是數組或字典。
集合的可變性
我們能夠定義一個集合常量或者集合變量。
一旦定義為常量,就意味着集合的長度、內容和順序都不能再改動了。比方,定義為常量的數組,不能再向當中加入新的元素。
數組的創建
由於swift中變量的創建遵循“ var 變量名:變量類型 ”的語法。因此數組的創建歸根結底還是數組類型的定義。
一共同擁有三種方法來定義數組的類型:
var arrayOne:Array<Int> = [1,2,3]
println("arrayLong = \(arrayOne)")
var arrayTwo:[Int] = [1,2,3]
println("arrayShort = \(arrayTwo)")
var arrayThree = [1,2,3]
println("arrayThree = \(arrayThree)")
第一種是數組類型的完整定義,即Array關鍵字加上一對尖括號,括號內寫上數組元素的類型。
另外一種是數組類型的簡化定義,即一對方括號內寫上數組元素的類型。這與第一種定義方法全然等價。
在使用這兩種方法定義數組的時候。一定要確保數組中每一個元素類型同樣,否則將會產生編譯錯誤。
第三種運用了Swift的類型推導的特性。須要注意的是。數組的值由方括號組成,里面的元素用逗號隔開。假設方括號改成了圓括號。編譯器不會報錯(這將變成元組),所以千萬要小心,避免莫名其妙的錯誤。
第三種方法除了書寫簡單之外,另一種優點,即不必確保數組中每一個元素類型同樣。我們來通過代碼看一看多個不同類型的元素出如今統一數組中會發生什么情況:
var arrayThree = [1,2,3]
println("arrayThree = \(arrayThree)")
var arrayMixed = [1,"abc",true, 1.5]
println("arrayMixed = \(arrayMixed)")//在這一行結束前設置斷點
//在LLDB調試當中分別輸入print arrayThree和print arrayMixed
能夠得到例如以下結果
([Int]) $R0 = 3 values {
[0] = 1
[1] = 2
[2] = 3
}
([NSObject]) $R1 = 4 values {
[0] = 0x0000000000000137 Int64(1)
[1] = "abc"
[2] = 0x00007fff7255e8a8 {
NSNumber = {
NSValue = (null)
}
}
[3] = 0x00000001006008a0 {
NSNumber = {
NSValue = (null)
}
}
}
因此不難發現,arrayMixed數組之所以能夠加入多個類型的元素,是由於它被推導為Array< NSObject>類型。同樣的,所以一旦數組的類型確定。就不能再插入不屬於這個類型的的值。
在我閱讀的教材上,作者特別提出。不指定類型的數組不能使用Array的append方法。
可是經過我的測試。並沒有這種限制。有興趣的讀者能夠自行測試,歡迎指正。
數組的訪問與改動
數組長度
能夠使用數組的僅僅讀屬性count來獲取數組長度:
var arrayThree = [1,2,3]
println("arrayThree.count = \(arrayThree.count)")
推斷數組為空
能夠使用數組的僅僅讀屬性isEmpty來推斷數組是否為空。當然通過推斷count是否為0也能夠達到同樣的效果,只是代碼略長一些。
var arrayThree = [1,2,3]
if !arrayThree.isEmpty{
println("Array Three is not empty")
}
加入新元素
一共同擁有兩種方法能夠在數組的尾部加入新元素:
//方法一,使用數組的append函數
var arrayThree = [1,2,3]
arrayThree.append(4)
println("arrayThree = \(arrayThree)")
//方法二。使用加法運算符
var arrayThree = [1,2,3]
arrayThree += [4]
println("arrayThree = \(arrayThree)")
不管使用哪種方法,都必須保證新加入的元素和數組類型同樣。
比方試圖像arrayThree中加入元素’1.5’會導致編譯錯誤。
能夠看到,另外一種方法的本質實際上是在兩個數組對象之間調用加法運算符,得到的結果是兩個數組拼接之后的結果。
因此,另外一種方法具有一個強大的功能,即向數組尾部加入多個元素。
另一種通用的方法,即調用數組的insert(atIndex:)方法。在指定位置插入新元素。
var arrayThree = [1,2,3]
arrayThree.insert(4, atIndex: 2)
println("arrayThree = \(arrayThree)")
刪除數組元素
能夠調用數組的removeAtIndex()和removeLast()方法。
var arrayThree = [1,2,3]
var numberThree = arrayThree.removeAtIndex(2)
var numberTwo = arrayThree.removeLast()
這兩個方法會返回被刪除的元素的值,當然假設不須要知道,能夠無視它的返回值,直接調用方法就可以。
須要注意的一點是,removeAtIndex方法首先要推斷下標是否越界。也就是說它會用到數組的長度。這意味着須要線性遍歷數組。因此假設僅僅須要移除數組的最后一個元素且數組長度非常大時。應該使用removeLast()方法。
訪問數組元素
了解了怎樣加入和刪除元素。我們就要想辦法把新加入的元素取出來看看了。通過數組下標能夠訪問指定位置的數組元素,語法與C語言同樣。
var arrayThree = [1,2,3]
println("ArrayThree[2] = \(arrayThree[2])")
改動數組元素
下標不僅能夠訪問數組元素。還能夠實現數組元素的改動。
這和訪問數組元素是非常相似的,僅僅要交換等號兩邊變量的位置就可以。
var arrayThree = [1,2,3]
var secondInt = arrayThree[1] //訪問元素
var newSecond = 4
arrayThree[2] = newSecond //改動數組元素
不僅如此,還能夠通過數組下標批量改動元素:
var arrayThree = [1,2,3]
var firstNumber = 1
var secondNumber = 2
arrayThree[0...1] = [firstNumber,secondNumber]
此時,等號的右側必須是數組的字面量,而不能是一個數組變量。
也就是說這種寫法是錯誤的:
var arrayThree = [1,2,3]
var newArray = [3,4]
var newSlice: ArraySlice<Int> = [3,4]
arrayThree[0...1] = newArray //錯誤。 arrayThree[0...1] = newSlice //正確
原因是左邊的arrayThree[0…1]事實上是一個SubArray,在Swift中它的類型叫做ArraySlice。即Int類型的數組切片,而右邊是一個Array類型變量,依據Swift類型安全的特性,這種操作自然是被禁止的。
假設左邊的切片長度和右邊的變量長度不一致會發生什么情況呢?不用過於操心,這不會產生不論什么錯誤。Swift會機智的幫我們解決問題。
var arrayOne:[Int] = [1,2,3]
var arrayTwo = [1,2,3]
var sliceOne:ArraySlice<Int> = [1,2,3]
var sliceTwo:ArraySlice<Int> = [1]
arrayOne[1...2] = sliceOne
arrayTwo[1...2] = sliceTwo
println("arrayOne = \(arrayOne)")
println("arrayTwo = \(arrayTwo)")
輸出結果各自是:
arrayOne = [1, 1, 2, 3]
arrayTwo = [1, 1]
因此。假設變量長度超過切片長度,將會自己主動在切片位置后加入元素(如同arrayOne),相當於調用了數組的insert(atIndex:)方法若干次。同樣地,假設變量長度少於切片長度,沒有值的位置的元素自己主動被移除,后面的元素自己主動向前補上。相當於調用了數組的removeAtIndex()方法若干次。
盡管這樣不會出現不論什么錯誤,只是出於邏輯嚴謹性考慮,應該避免等號兩端變量長度不一樣的情況。
數組遍歷
之前我們介紹了數組的增刪改操作,還缺少一個查找。
也就是數組的遍歷。
在Swift中,除了像C語言那樣定義一個下標變量,在for循環中遍歷數組,還有兩種方式遍歷數組。
//方法一,使用for in循環高速遍歷
var array = [1,2,3,2,1,32,99]
for number in array{
println("number = \(number)")
}
通過觀察輸出結果能夠發現。for in循環是依照從前向后的順序遍歷數組的。
//方法二:使用enumerate函數
var array = [1,2,3,2,1,32,99]
for (index, value) in enumerate(array){ println("value = \(value)") }
enumerate(array)方法的返回值是一個數組。數組中的每一個元素都是一個二元元組。第一個值是下標index。第二個值是元素的值。這個方案也是順序遍歷數組。
數組的初始化
在本章的開頭。我們利用數組字面量來初始化一個數組。事實上,數組還有其它的初始化方法。
首先類比字符串的構造方法var string = String(),我們能夠得知數組的另外兩種構造方法。
var arrayOne = [Int]()
var arrayTwo = Array<Int>()
println("第一個數組元素個數為:\(arrayOne.count)")
println("第二個數組元素個數為:\(arrayTwo.count)")
執行結果:
第一個數組元素個數為:0
第二個數組元素個數為:0
除此以外,數組另一種特殊的構造方法,能夠指定數組長度,在這種情況下還必須強制指定數組中每一個元素的值。
假設覺得無用的話。能夠先設置為0,然后再改動。
var arrayThree = [Int](count: 5, repeatedValue: 0)
var arrayFour = Array<Int>(count: 5, repeatedValue: 0)
var arrayFiver = Array(count: 5, repeatedValue: 0)
print("第三個數組為:\(arrayThree)")
print("第四個數組為:\(arrayFour)")
print("第五個數組為:\(arrayFiver)")
得益於類型推導,第五種數組初始化方法也是合法的。
可是之前的標准初始化方法不能夠這么簡化。輸出結果例如以下:
第三個數組為:[0, 0, 0, 0, 0]
第四個數組為:[1, 1, 1, 1, 1]
第五個數組為:[2, 2, 2, 2, 2]
附錄
查看完整專欄——《Swift輕松入門》
【Swift入門(一)——基本的語法】
【Swift入門(二)——字符與字符串】
【Swift入門(三)——元組(Tuple)】
【Swift入門(四)——可選類型(Optionals)與斷言(Assert)】
【Swift入門(五)——數組(Array)】
【Swift入門(六)——字典(Dictionary)】
【Swift入門(七)——結構體(Struct)】
【Swift入門(八)——功能強大的求余運算符】
【Swift入門(九)——String與Int、Double、Float等數字相互轉換】
【Swift入門(十)——循環引用、弱引用和無主引用】
【Swift入門(十一)——類型轉換與is、as操作】
【Swift入門(十二)——利用Extension加入逆序輸出字符串方法】
