Swift中的集合类型

一.引子:

        在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


posted on 2017-05-13 15:57  ljbguanli  阅读(158)  评论(0编辑  收藏  举报