1. 程式人生 > >Swift中的集合類型

Swift中的集合類型

寫法 short append fine 安全 clas 奔馳 刪除元素 net

一.引子:

在2014年10月TIOBE編程語言排行榜中,Swift位居第18位。從2014WWDC發布會首次發布至今不到半年時間,swift一直受到編程人員的追捧,其熱衷程度並不亞於當紅巨星Taylor Swift。相信在不遠的將來。swift可以平穩發展。並逐步代替Objective-C。


二.swift的集合類型

以下回歸主題。作為一名iOS開發人員。我們已經很熟悉諸如NSArray,NSDictionary,NSSet等常見集合類型。以及它們的可變同類NSMutableArray,NSMutableDictionary,NSMutableSet。而swift則為我們提供了原生的Array和Dictionary集合類型,遺憾的是。眼下還沒有提供Set這種集合類型(估計將來可能會加入進去)。

與Objective-C不同的是,swift不存在相應的mutable類型。原因是一個集合類型是否可變是通過修飾符var和let決定的。因此。假設一個集合類型的變量是let修飾的。則這個集合類型是不可變的。假設一個集合類型的變量是var修飾的,則這個集合類型是可變的。

比如:

var mutableArray = Array<Int>()

mutableArray.append(1)

let immutableArray = Array<String>()

immutableArray.append("item")    // 編譯時錯誤

假設不知道修飾符let和var的差別,能夠這樣簡單理解。let修飾的變量是常量,一旦賦值後就不能再改變。而var修飾的變量的值能夠動態改變。


三.範型集合

Objective-C的集合類型對集合裏的元素僅僅有一個要求。那就是它必須是一個OC對象(非常多時候我們想要往裏面加入基本數據類型時。都要用NSNumber封裝一下才幹放到集合裏去)。而swift則不同。swift宣稱自己是類型安全的,由於swift的特性裏包括現代語言裏都會有的範型(generic)。因此我們在調用集合類型的初始化方法時,都要註明這個集合類型的元素數據類型。

比方:

var intArray = Array<Int>()

intArray.append(2014)

intArray.append("2014")    // 編譯時錯誤

var creditDictionary = Dictionary<String,Int>()

creditDictionary.updateValue(88888, forKey: "Benson")


在上面的樣例中,聲明了一個整形數組和一個KeyType為String,ValueType為Int的字典。

整形數組裏僅僅能存放整形元素。假設放入字符串元素,編譯器就會報錯(值得註意的是,假設放入浮點類型或者布爾類型,編譯器會自己主動將其轉換為整形,比方3.14轉換成3。true轉換為1)。有了範型,就能夠確保類型安全,而不用再進行類型推斷和強制類型轉換等麻煩操作。

(數組的元素類型沒有不論什麽限制。可是字典對KeyType設定了類型限制(Type Constraints)。它規定KeyType必須實現Hashable協議,該協議規定遵循類必須提供gettable的hashValue屬性。值得慶幸的是,String,Int,Double,Bool等經常使用類型都實現了該協議,普通情況下夠用了。)

四.簡寫形式

對於集合類型的初始化,大多數情況下都不採用上面樣例中的寫法。而是採用更加簡潔的形式。

var shorthandArray = [Int]()    // var intArray = Array<Int>()

var shorthandDictionary = [String:Int]()    // var creditDictionary = Dictionary<String,Int>()

如上所看到的,對於數組類型來說,僅僅需在中括號中聲明數組的類型。接著再跟一對小括號就可以(小括號中也可帶有初始化的參數,比方[Int](count:3,repeatedValue:0) )。對於字典類型來說,僅僅需再中括號中聲明key和value的類型,並以冒號分隔就可以,接著再跟一對小括號,同理。小括號中也可帶有對應初始化方法的參數。第二種情況是,假設已知某個變量為集合類型,那麽再次賦值時能夠採用更簡單的形式:

shorthandArray = [] // empty array

shorthandDictionary = [:]   // empty dictionary

因為類型已知,因此無需在中括號裏聲明對應的類型。


五.集合類型的遍歷

集合類型最經常使用的操作莫過於遍歷集合。以下分別針對數組和字典進行遍歷:

var carArray = [String]()

carArray.append("Mercedes-Benz")
carArray.append("Toyota")
carArray.append("Porsche")

for car in carArray {
    println(car)
}

上面的樣例中採用for in 循環。循環打印數組中每一個元素。(println是swift內置全局函數。類似於java的System.out.println()方法。

另外能夠看到for循環中無需用小括號包圍)

輸出結果:

技術分享(這水印。

)


假設在循環過程中須要得到索引值,能夠使用swift標準庫中的全局函數enumerate:

for (index,value) in enumerate(carArray) {
    println("index\(index):\(value)")
}

打印結果:

index0:Mercedes-Benz
index1:Toyota
index2:Porsche

接下來是遍歷字典:

var animalLegs = [String:Int]()

animalLegs.updateValue(4, forKey: "deer")
animalLegs.updateValue(8, forKey: "crab")
animalLegs.updateValue(2, forKey: "kangaroo")

for (animal,legs) in animalLegs {
    println("\(animal) has \(legs)leg(s)")
}

和遍歷數組類似,僅僅只是遍歷的每一項是一個元組(tuple)。該元組包括兩個元素,一個是key,一個是value。


六.使用下標(subscript)

數組Array和字典Dictionary能夠使用下標的形式進行加入,刪除和替換等操作,比方:

var carArray = [String]()

carArray.append("Mercedes-Benz")
carArray.append("Toyota")
carArray.append("Porsche")

carArray[0] = "BMW"  // 奔馳被替換成寶馬了 [ replace 操作]

var animalLegs = [String:Int]()

animalLegs.updateValue(4, forKey: "deer")
animalLegs.updateValue(8, forKey: "crab")
animalLegs.updateValue(2, forKey: "kangaroo")

animalLegs["sheep"] = 4     // 加入一個元素

animalLegs["deer"] = nil    // 刪除一個元素

animalLegs["crab"] = 6      // 替換元素的值

if let legs = animalLegs["kangaroo"] {
    println("kangaroo has \(legs)legs")
} else {
    println("not defined")
}

針對數組的操作,下標好像僅僅能進行替換,不能加入元素,也不能刪除元素(假設將某個元素設置為nil,需將數組的元素類型設置為optional)。

針對字典的操作則比較齊全,能夠進行CRUD。須要特別註意的是,通過下標獲取字典某個key的值的時候。返回的類型是ValueType?(即optional的值類型)。能夠採用optional binding或者if和!搭配使用提取該值。由於字典中可能不存在該值,從而可能為nil。


七.集合類型的簡便初始化

可能是說漏了,但也是最重要的一點。就是怎樣利用數組和字典的字面量(literal)對變量進行賦值。

var countryArray = ["China","Japan","Russia","India","Canada"]

var festivalDic = ["National‘s Day":"10-01","Christmas Day":"12-25","New Year":"01-01"]

數組的字面量一般形式是[value,value,value...],字典的一般形式是[key:value,key:value,key:value,...]。數組和字典的數據類型是通過類型推導(type inferrence)得出來的,對於數組來說,因為數組裏的元素都是String,因此countryArray的數據類型是[String],同理,festivalDic的數據類型是[String:String]。


最後須要強調一點的是,Array和Dictionary跟OC的NSArray和NSDictionary不同。Array和Dictionary是值類型(value type),不是引用類型。因此。Array和Dictionary傳值一般都是copy,其原始值不會受到影響:(更詳細一點。Array和Dictionary都是struct類型,String也不例外。)

var original = [1,2,3]

var steal = original

steal.append(4)

original.count // 3

steal.count    // 4


Swift中的集合類型