• Swift----函数 、 闭包 、 枚举 、 类和结构体 、 属性


    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,该参数用于提供数组的排序规则,代码如下所示:

    1. funcsortInts(inout data:[Int],rule:(Int,Int)->Bool) {
    2. }

    然后实现函数sortInts,这里采用数组的冒泡排序算法来实现排序,代码如下所示:

     
    1. funcsortInts(inout data:[Int],rule:(Int,Int)->Bool) {
    2. forvari=0;i < data.count-1;i++ {
    3. forvar j=0;j<data.count-i-1;j++ {
    4. if rule(data[j], data[j+1]) {
    5. swap(&data[j], &data[j+1])
    6. }
    7. }
    8. }
    9. }

    步骤二:实现规则函数

    sortInts函数的rule参数是一个函数类型,需要调用时进行传递,该参数用于决定数组的排序规则,可以进行自定义,也就是由程序员来根据程序需求自定义排序规则。

    接下来实现一个数组排序的规则函数rule1,该函数是(Int,Int)->Bool类型,可以将该函数设置为sortInts函数rule1规则的默认值,代码如下所示:

     
    1. func rule1(a:Int,b:Int)->Bool {
    2. return a > b
    3. }
    4. //函数类型作为参数传递
    5. funcsortInts(inout data:[Int],rule:(Int,Int)->Bool = rule1) {
    6. forvari=0;i < data.count-1;i++ {
    7. forvar j=0;j<data.count-i-1;j++ {
    8. if rule(data[j], data[j+1]) {
    9. swap(&data[j], &data[j+1])
    10. }
    11. }
    12. }
    13. }

    最后将一个整型数组a,传递给函数调用,使用默认规则实现数组a的排序,代码如下所示:

    1. var a = [1,3,2,4,9,8,5,0,6,7]
    2. sortInts(&a)

    运行结果如图-1所示:

    图-1

    当然也可以自定义规则传递给函数sortInts,代码如下所示:

    1. //自定义排序规则
    2. func rule2(a:Int,b:Int)->Bool {
    3. return a<b
    4. }
    5. sortInts(&a, rule: rule2)
    6. func rule3(a:Int, b:Int)->Bool {return a%3 > b%3}
    7. sortInts(&a, rule: rule3)

    运行结果如图-2所示:

    图-2

    1.4 完整代码

    本案例中,完整代码如下所示:

     
    1. importUIKit
    2. func rule1(a:Int,b:Int)->Bool {
    3. return a > b
    4. }
    5. //函数类型作为参数传递
    6. funcsortInts(inout data:[Int],rule:(Int,Int)->Bool = rule1) {
    7. forvari=0;i < data.count-1;i++ {
    8. forvar j=0;j<data.count-i-1;j++ {
    9. if rule(data[j], data[j+1]) {
    10. swap(&data[j], &data[j+1])
    11. }
    12. }
    13. }
    14. }
    15. var a = [1,3,2,4,9,8,5,0,6,7]
    16. sortInts(&a)
    17. a
    18. //自定义排序规则
    19. func rule2(a:Int,b:Int)->Bool {
    20. return a<b
    21. }
    22. sortInts(&a, rule: rule2)
    23. func rule3(a:Int, b:Int)->Bool {return a%3 > b%3}
    24. 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,代码如下所示:

    1. letdigitNames = [
    2. 0: "零", 1: "一", 2: "二", 3: "三", 4: "四",5: "五", 6: "六", 7: "七", 8: "八", 9: "九"]
    3. let numbers = [16, 58, 510]

    步骤二:调用map方法

    numbers数组调用map方法,该方法需要传递一个闭包表达式用于规定映射规则,这里采用尾随闭包的形式,代码如下所示:

     
    1. numbers.map {(var number) -> String in
    2. var output = ""
    3. while number > 0 {
    4. //字典下标返回一个可选值
    5. output = digitNames[number % 10]! + output
    6. number /= 10
    7. }
    8. return output
    9. }

    map函数是数组的方法,可以迭代数组中每一元素传入闭包执行一次,并将执行后的结果做成一个数组返回回来,运行结果如图-3所示:

    图-3

    2.4 完整代码

    本案例中,完整代码如下所示:

     
    1. importUIKit
    2. letdigitNames = [
    3. 0: "零", 1: "一", 2: "二", 3: "三", 4: "四",5: "五", 6: "六", 7: "七", 8: "八", 9: "九"]
    4. let numbers = [16, 58, 510]
    5. //map函数是数组的方法,可以迭代数组中每一元素传入闭包执行一次,并将执行后的结果做成一个数组返回回来
    6. let strings = numbers.map {(var number)->String in
    7. var output = ""
    8. while number > 0 {
    9. output = digitNames[number%10]!+output
    10. number/=10
    11. }
    12. return output
    13. }
    14. 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类型,代码如下所示:

    1. enum Barcode{
    2. case UPCA(Int, Int, Int)
    3. caseQRCode(String)
    4. }

    枚举的定义不提供任何Int或String的实际值,只是定义而已。

    步骤二:使用关联值

    使用刚才定义的枚举类型Barcode创建一个新的变量productBarcode,并且赋给它两个成员的关联值,代码如下所示:

    1. varproductBarCode : Barcode = Barcode.UPCA(692, 530372375, 0)
    2. productBarCode = Barcode.QRCode("ABCDEFSFD")

    不同的条形码可以使用一个switch语句来检查,代码如下所示:

     
    1. switchproductBarCode {
    2. case .UPCA(let(num, id, check)):
    3. println("这是条形码(num)-(id)-(check)")
    4. case .QRCode(let pCode):
    5. println("这是二维码(pCode)")
    6. }

    然后调用函数,运行结果如图-6所示:

    图-6

    3.4 完整代码

    本案例中,完整代码如下所示:

     
    1. importUIKit
    2. //关联值
    3. enum Barcode{
    4. case UPCA(Int, Int, Int)
    5. caseQRCode(String)
    6. }
    7. varproductBarCode : Barcode = Barcode.UPCA(692, 530372375, 0)
    8. productBarCode = Barcode.QRCode("ABCDEFSFD")
    9. switchproductBarCode {
    10. case .UPCA(let(num, id, check)):
    11. println("这是条形码(num)-(id)-(check)")
    12. case .QRCode(let pCode):
    13. println("这是二维码(pCode)")
    14. }
     

    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,用于表示长宽,代码如下所示:

     
    1. struct Point {
    2. //存储属性
    3. var x = 0.0
    4. var y = 0.0
    5. }
    6. struct Size {
    7.      //存储属性
    8. var width = 0.0
    9. var height = 0.0
    10. }

    步骤二:定义Rect结构体

    然后定义矩形Rect结构体,该结构体有两个存储属性一个是Point类型的origin,用于表示原点坐标,另一个是Size类型的size,用于表示矩形的长宽,代码如下所示:

     
    1. structRect {
    2. //存储属性
    3. var origin = Point()
    4. var size = Size()
    5. }

    Rect结构体还有一个Point类型的计算属性center,用于表示矩形的中心点,需要提供getter和setter方法获取和设置其值,代码如下所示:

     
    1. structRect {
    2. //存储属性
    3. var origin = Point()
    4. var size = Size()
    5. //计算属性
    6. varcenter:Point {
    7. get {
    8. letcenterX = origin.x + size.width/2
    9. letcenterY = origin.y + size.height/2
    10. return Point(x: centerX, y: centerY)
    11. }
    12. set(newCenter) {
    13. origin.x = newCenter.x - size.width/2
    14. origin.y = newCenter.y - size.height/2
    15. }
    16. }
    17. }

    步骤三:创建square实例

    创建一个Rect实例square,原点坐标设置为(0.0,0.0),长宽设置为(10.0,10.0),可以通过点运算调用getter方法获取到center属性的值,代码如下所示:

    1. var square = Rect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 10.0))
    2. letcenterSquare = square.center

    可以看到center的值为(5.0,5.0),运行结果如图-8所示:

    图-8

    然后重新设置center的值(15,15),设置属性center的值会调用setter来修改该属性origin的值,代码如下所示:

     
    1. square.center = Point(x: 15, y: 15)

    可以看到此时square的origin属性的值为(10,10),运行结果如图-9所示:

    图-9

    4.4 完整代码

    本案例中,完整代码如下所示:

     
    1. importUIKit
    2. struct Point {
    3. //存储属性
    4. var x = 0.0
    5. var y = 0.0
    6. }
    7. struct Size {
    8. //存储属性
    9. var width = 0.0
    10. var height = 0.0
    11. }
    12. structRect {
    13. //存储属性
    14. var origin = Point()
    15. var size = Size()
    16. //计算属性
    17. varcenter:Point {
    18. get {
    19. letcenterX = origin.x + size.width/2
    20. letcenterY = origin.y + size.height/2
    21. return Point(x: centerX, y: centerY)
    22. }
    23. set(newCenter) {
    24. origin.x = newCenter.x - size.width/2
    25. origin.y = newCenter.y - size.height/2
    26. }
    27. }
    28. }
    29. var square = Rect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 10.0))
    30. letcenterSquare = square.center
    31. square.center = Point(x: 15, y: 15)
  • 相关阅读:
    极速安装JumpServer
    高并发限流策略
    JDK1.8源码分析:Future和FutureTask-任务异步执行结果
    nginx 转发 header 数据丢失
    zookpeer 和 redis 集群内一致性协议 及 选举 对比
    Spring Boot 中 Druid 的监控页面配置
    eclipse使用正则表达式查找替换
    jvm 线程状态
    Redis做分布式锁
    Dubbo的异常处理
  • 原文地址:https://www.cnblogs.com/52190112cn/p/5052162.html
Copyright © 2020-2023  润新知