1 数组排序
1.1 问题
本案例实现一个整型数组排序的函数,数组排序的规则由传递的规则函数决定。
1.2 方案
首先定义一个整型数组排序函数sortInts,该函数有一个整型数组类型的参数,该参数必须是输入输出参数inout,否则并不能修改数组的值。另外还有一个(Int,Int)->Bool函数类型的参数rule,该参数用于提供数组的排序规则。
然后实现函数sortInts,这里采用数组的冒泡排序算法来实现排序。
接下来实现一个数组排序的规则函数rule1,该函数是(Int,Int)->Bool类型,可以将该函数设置为sortInts函数rule1规则的默认值。
最后将一个整型数组a,传递给函数调用,就能实现数组a的排序。当然也可以自定义规则传递给函数sortInts。
1.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:定义整型数组排序函数sortInts
首先定义一个整型数组排序函数sortInts,该函数有一个整型数组类型的参数,该参数必须是输入输出参数inout,否则并不能修改数组的值。另外还有一个(Int,Int)->Bool函数类型的参数rule,该参数用于提供数组的排序规则,代码如下所示:
- funcsortInts(inout data:[Int],rule:(Int,Int)->Bool) {
- }
然后实现函数sortInts,这里采用数组的冒泡排序算法来实现排序,代码如下所示:
- funcsortInts(inout data:[Int],rule:(Int,Int)->Bool) {
- forvari=0;i < data.count-1;i++ {
- forvar j=0;j<data.count-i-1;j++ {
- if rule(data[j], data[j+1]) {
- swap(&data[j], &data[j+1])
- }
- }
- }
- }
步骤二:实现规则函数
sortInts函数的rule参数是一个函数类型,需要调用时进行传递,该参数用于决定数组的排序规则,可以进行自定义,也就是由程序员来根据程序需求自定义排序规则。
接下来实现一个数组排序的规则函数rule1,该函数是(Int,Int)->Bool类型,可以将该函数设置为sortInts函数rule1规则的默认值,代码如下所示:
- func rule1(a:Int,b:Int)->Bool {
- return a > b
- }
- //函数类型作为参数传递
- funcsortInts(inout data:[Int],rule:(Int,Int)->Bool = rule1) {
- forvari=0;i < data.count-1;i++ {
- forvar j=0;j<data.count-i-1;j++ {
- if rule(data[j], data[j+1]) {
- swap(&data[j], &data[j+1])
- }
- }
- }
- }
最后将一个整型数组a,传递给函数调用,使用默认规则实现数组a的排序,代码如下所示:
- var a = [1,3,2,4,9,8,5,0,6,7]
- sortInts(&a)
运行结果如图-1所示:
图-1
当然也可以自定义规则传递给函数sortInts,代码如下所示:
- //自定义排序规则
- func rule2(a:Int,b:Int)->Bool {
- return a<b
- }
- sortInts(&a, rule: rule2)
- func rule3(a:Int, b:Int)->Bool {return a%3 > b%3}
- sortInts(&a, rule: rule3)
运行结果如图-2所示:
图-2
1.4 完整代码
本案例中,完整代码如下所示:
- importUIKit
- func rule1(a:Int,b:Int)->Bool {
- return a > b
- }
- //函数类型作为参数传递
- funcsortInts(inout data:[Int],rule:(Int,Int)->Bool = rule1) {
- forvari=0;i < data.count-1;i++ {
- forvar j=0;j<data.count-i-1;j++ {
- if rule(data[j], data[j+1]) {
- swap(&data[j], &data[j+1])
- }
- }
- }
- }
- var a = [1,3,2,4,9,8,5,0,6,7]
- sortInts(&a)
- a
- //自定义排序规则
- func rule2(a:Int,b:Int)->Bool {
- return a<b
- }
- sortInts(&a, rule: rule2)
- func rule3(a:Int, b:Int)->Bool {return a%3 > b%3}
- sortInts(&a, rule: rule3)
2 将Int数组转换为对应的String类型的数组
2.1 问题
如果需要将一个很长的闭包表达式作为最后一个参数传递给函数,可以使用尾随闭包来增强函数的可读性。本案例在Array的map方法中使用尾随闭包将一个Int类型的数组[16, 58, 510]转换为对应的String类型的数组["一六", "五八", "五一零"]。
2.2 方案
Array类型有一个map方法,唯一参数是一个闭包表达式,数组中的每一个元素调用用一次该闭包函数,并返回该元素所映射的值,具体的映射方式由闭包表达式决定。
当提供给数组闭包函数后,map方法将返回一个新的数组,数组中包含了与原数组一一对应的映射后的值。
2.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:创建字典digiNames
创建一个数字和中文名映射的字典digiNames,代码如下所示:
- letdigitNames = [
- 0: "零", 1: "一", 2: "二", 3: "三", 4: "四",5: "五", 6: "六", 7: "七", 8: "八", 9: "九"]
- let numbers = [16, 58, 510]
步骤二:调用map方法
numbers数组调用map方法,该方法需要传递一个闭包表达式用于规定映射规则,这里采用尾随闭包的形式,代码如下所示:
- numbers.map {(var number) -> String in
- var output = ""
- while number > 0 {
- //字典下标返回一个可选值
- output = digitNames[number % 10]! + output
- number /= 10
- }
- return output
- }
map函数是数组的方法,可以迭代数组中每一元素传入闭包执行一次,并将执行后的结果做成一个数组返回回来,运行结果如图-3所示:
图-3
2.4 完整代码
本案例中,完整代码如下所示:
- importUIKit
- letdigitNames = [
- 0: "零", 1: "一", 2: "二", 3: "三", 4: "四",5: "五", 6: "六", 7: "七", 8: "八", 9: "九"]
- let numbers = [16, 58, 510]
- //map函数是数组的方法,可以迭代数组中每一元素传入闭包执行一次,并将执行后的结果做成一个数组返回回来
- let strings = numbers.map {(var number)->String in
- var output = ""
- while number > 0 {
- output = digitNames[number%10]!+output
- number/=10
- }
- return output
- }
- strings
3 定义商品条形码的枚举
3.1 问题
假设一个仓库跟踪系统需要利用两种不同类型的条形码来跟踪商品,有些商品上标有UPC-A格式的一维码,它是由三个整型数字组成。另外其他一些商品上标有QR格式的二维码,它是一个字符串,如图-4、图-5所示:
图-4
图-5
本案例要求使用枚举来表示商品条码并设置其关联值。
3.2 方案
首先把UPC-A码作为三个整型值的元组,把QR码作为一个任字符串存储起来,那么定义一个枚举Barcode并设置器关联值。
3.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:定义枚举Barcode
定义一个枚举Barcode表示商品条形码,它有两个成员UPCA和QRCode,UPCA的关联值是一个包含三个整型值的元组类型,QRCode的关联值是一个String类型,代码如下所示:
- enum Barcode{
- case UPCA(Int, Int, Int)
- caseQRCode(String)
- }
枚举的定义不提供任何Int或String的实际值,只是定义而已。
步骤二:使用关联值
使用刚才定义的枚举类型Barcode创建一个新的变量productBarcode,并且赋给它两个成员的关联值,代码如下所示:
- varproductBarCode : Barcode = Barcode.UPCA(692, 530372375, 0)
- productBarCode = Barcode.QRCode("ABCDEFSFD")
不同的条形码可以使用一个switch语句来检查,代码如下所示:
- switchproductBarCode {
- case .UPCA(let(num, id, check)):
- println("这是条形码\(num)-\(id)-\(check)")
- case .QRCode(let pCode):
- println("这是二维码\(pCode)")
- }
然后调用函数,运行结果如图-6所示:
图-6
3.4 完整代码
本案例中,完整代码如下所示:
- importUIKit
- //关联值
- enum Barcode{
- case UPCA(Int, Int, Int)
- caseQRCode(String)
- }
- varproductBarCode : Barcode = Barcode.UPCA(692, 530372375, 0)
- productBarCode = Barcode.QRCode("ABCDEFSFD")
- switchproductBarCode {
- case .UPCA(let(num, id, check)):
- println("这是条形码\(num)-\(id)-\(check)")
- case .QRCode(let pCode):
- println("这是二维码\(pCode)")
- }
4 定义几何形状的结构体
4.1 问题
属性分为存储属性和计算属性,存储属性就是用常量或变量保存的属性值。计算属性的值是通过计算得出的。
按如下要求完成本案例:
1)定义一个Point结构体,用于表示点坐标(x,y);
2)定义一个Size结构体,用于表示形状的长和宽(width,height);
3)定义一个Rect结构体,用于表示有原点和尺寸的矩形,还提供一个表示中心点center的计算属性;
4)创建一个Rect类型的实例square,并设置和修改center属性移动矩形,如图-7所示:
图-7
4.2 方案
首先定义Point结构体和Size结构体,Point结构有两个存储属性x和y,用于表示点坐标。Size结构体也有两个存储属性width和height,用于表示长宽。
然后定义矩形Rect结构体,该结构体有两个存储属性一个是Point类型的origin,用于表示原点坐标,另一个是Size类型的size,用于表示矩形的长宽。
Rect结构体还有一个Point类型的计算属性center,用于表示矩形的中心点,需要提供getter和setter方法获取和设置其值。
最后创建一个Rect实例square,设置和修改center属性,查看输出结果。
4.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:定义Point和Size结构体
首先定义Point结构体和Size结构体,Point结构有两个存储属性x和y,用于表示点坐标。Size结构体也有两个存储属性width和height,用于表示长宽,代码如下所示:
- struct Point {
- //存储属性
- var x = 0.0
- var y = 0.0
- }
- struct Size {
- //存储属性
- var width = 0.0
- var height = 0.0
- }
步骤二:定义Rect结构体
然后定义矩形Rect结构体,该结构体有两个存储属性一个是Point类型的origin,用于表示原点坐标,另一个是Size类型的size,用于表示矩形的长宽,代码如下所示:
- structRect {
- //存储属性
- var origin = Point()
- var size = Size()
- }
Rect结构体还有一个Point类型的计算属性center,用于表示矩形的中心点,需要提供getter和setter方法获取和设置其值,代码如下所示:
- structRect {
- //存储属性
- var origin = Point()
- var size = Size()
- //计算属性
- varcenter:Point {
- get {
- letcenterX = origin.x + size.width/2
- letcenterY = origin.y + size.height/2
- return Point(x: centerX, y: centerY)
- }
- set(newCenter) {
- origin.x = newCenter.x - size.width/2
- origin.y = newCenter.y - size.height/2
- }
- }
- }
步骤三:创建square实例
创建一个Rect实例square,原点坐标设置为(0.0,0.0),长宽设置为(10.0,10.0),可以通过点运算调用getter方法获取到center属性的值,代码如下所示:
- var square = Rect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 10.0))
- letcenterSquare = square.center
可以看到center的值为(5.0,5.0),运行结果如图-8所示:
图-8
然后重新设置center的值(15,15),设置属性center的值会调用setter来修改该属性origin的值,代码如下所示:
- square.center = Point(x: 15, y: 15)
可以看到此时square的origin属性的值为(10,10),运行结果如图-9所示:
图-9
4.4 完整代码
本案例中,完整代码如下所示:
- importUIKit
- struct Point {
- //存储属性
- var x = 0.0
- var y = 0.0
- }
- struct Size {
- //存储属性
- var width = 0.0
- var height = 0.0
- }
- structRect {
- //存储属性
- var origin = Point()
- var size = Size()
- //计算属性
- varcenter:Point {
- get {
- letcenterX = origin.x + size.width/2
- letcenterY = origin.y + size.height/2
- return Point(x: centerX, y: centerY)
- }
- set(newCenter) {
- origin.x = newCenter.x - size.width/2
- origin.y = newCenter.y - size.height/2
- }
- }
- }
- var square = Rect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 10.0))
- letcenterSquare = square.center
- square.center = Point(x: 15, y: 15)