• 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修饰的,则这个集合类型是可变的。例如:

    1. var mutableArray = Array<Int>()  
    2.   
    3. mutableArray.append(1)  
    4.   
    5. let immutableArray = Array<String>()  
    6.   
    7. immutableArray.append("item")    // 编译时错误  


    如果不知道修饰符let和var的区别,可以这样简单理解,let修饰的变量是常量,一旦赋值后就不能再改变。而var修饰的变量的值可以动态改变。


    三.范型集合

            Objective-C的集合类型对集合里的元素只有一个要求,那就是它必须是一个OC对象(很多时候我们想要往里面添加基本数据类型时,都要用 NSNumber封装一下才能放到集合里去)。而swift则不同,swift宣称自己是类型安全的,因为swift的特性里包含现代语言里都会有的范型 (generic)。因此我们在调用集合类型的初始化方法时,都要注明这个集合类型的元素数据类型。比如:

    1. var intArray = Array<Int>()  
    2.   
    3. intArray.append(2014)  
    4.   
    5. intArray.append("2014")    // 编译时错误  
    6.   
    7. var creditDictionary = Dictionary<String,Int>()  
    8.   
    9. 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等常用类型都实现了该协议,一般情况下够用了。)

    四.简写形式

            对于集合类型的初始化,大多数情况下都不采用上面例子中的写法,而是采用更加简洁的形式。

    1. var shorthandArray = [Int]()    // var intArray = Array<Int>()  
    2.   
    3. var shorthandDictionary = [String:Int]()    // var creditDictionary = Dictionary<String,Int>()  


    如上所示,对于数组类型来说,只需在中括号中声明数组的类型,接着再跟一对小括号即可(小括号里也可带有初始化的参数,比如[Int] (count:3,repeatedValue:0) ),对于字典类型来说,只需再中括号中声明key和value的类型,并以冒号分隔即可,接着再跟一对小括号,同理,小括号里也可带有相应初始化方法的参 数。另外一种情况是,如果已知某个变量为集合类型,那么再次赋值时可以采用更简单的形式:

    1. shorthandArray = [] // empty array  
    2.   
    3. shorthandDictionary = [:]   // empty dictionary  


    由于类型已知,因此无需在中括号中声明相应的类型。


    五.集合类型的遍历

        集合类型最常用的操作莫过于遍历集合。下面分别针对数组和字典进行遍历:

    1. var carArray = [String]()  
    2.   
    3. carArray.append("Mercedes-Benz")  
    4. carArray.append("Toyota")  
    5. carArray.append("Porsche")  
    6.   
    7. for car in carArray {  
    8.     println(car)  
    9. }  


    上面的例子中采用for in 循环,循环打印数组中每个元素。(println是swift内置全局函数,类似于java的System.out.println()方法。另外可以看到for循环中无需用小括号包围)

    输出结果:

    (这水印。。)


    如果在循环过程中需要得到索引值,可以使用swift标准库中的全局函数enumerate:

    1. for (index,value) in enumerate(carArray) {  
    2.     println("index(index):(value)")  
    3. }  


    打印结果:

    1. index0:Mercedes-Benz  
    2. index1:Toyota  
    3. index2:Porsche  


    接下来是遍历字典:

    1. var animalLegs = [String:Int]()  
    2.   
    3. animalLegs.updateValue(4, forKey: "deer")  
    4. animalLegs.updateValue(8, forKey: "crab")  
    5. animalLegs.updateValue(2, forKey: "kangaroo")  
    6.   
    7. for (animal,legs) in animalLegs {  
    8.     println("(animal) has (legs)leg(s)")  
    9. }  


    和遍历数组类似,只不过遍历的每一项是一个元组(tuple),该元组包含两个元素,一个是key,一个是value。


    六.使用下标(subscript)

        数组Array和字典Dictionary可以使用下标的形式进行添加,删除和替换等操作,比如:

    1. var carArray = [String]()  
    2.   
    3. carArray.append("Mercedes-Benz")  
    4. carArray.append("Toyota")  
    5. carArray.append("Porsche")  
    6.   
    7. carArray[0] = "BMW"  // 奔驰被替换成宝马了 [ replace 操作]  
    8.   
    9. var animalLegs = [String:Int]()  
    10.   
    11. animalLegs.updateValue(4, forKey: "deer")  
    12. animalLegs.updateValue(8, forKey: "crab")  
    13. animalLegs.updateValue(2, forKey: "kangaroo")  
    14.   
    15. animalLegs["sheep"] = 4     // 添加一个元素  
    16.   
    17. animalLegs["deer"] = nil    // 删除一个元素  
    18.   
    19. animalLegs["crab"] = 6      // 替换元素的值  
    20.   
    21. if let legs = animalLegs["kangaroo"] {  
    22.     println("kangaroo has (legs)legs")  
    23. } else {  
    24.     println("not defined")  
    25. }  


    针对数组的操作,下标好像只能进行替换,不能添加元素,也不能删除元素(如果将某个元素设置为nil,需将数组的元素类型设置为optional)。

    针对字典的操作则比较齐全,可以进行CRUD。需要特别注意的是,通过下标获取字典某个key的值的时候,返回的类型是ValueType?(即 optional的值类型),可以采用optional binding或者if和!搭配使用提取该值,因为字典中可能不存在该值,从而可能为nil。


    七.集合类型的简便初始化

        可能是说漏了,但也是最重要的一点,就是如何利用数组和字典的字面量(literal)对变量进行赋值。

    1. var countryArray = ["China","Japan","Russia","India","Canada"]  
    2.   
    3. 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也不例外。)

      1. var original = [1,2,3]  
      2.   
      3. var steal = original  
      4.   
      5. steal.append(4)  
      6.   
      7. original.count // 3  
      8.   
      9. steal.count    // 4 
  • 相关阅读:
    《Linux系统free命令的使用》学习笔记
    《postfix MAIL服务搭建(第一篇):》RHEL6
    RHEL(RedHat Enterprise Linux)5/6 ISO镜像下载
    《samba搭建win客户端和linux客户端的区别》
    《怎样实现通过shell脚本将用户踢出系统》
    《DDNS服务器的搭建和案例解决方法》
    《Usermod:user lee is currently logged in 家目录不能改变解决方法》
    你们看不懂为什么写这个博客吧
    JS几种数组遍历方式以及性能分析对比
    从概念到业务来看 To B 和 To C 产品区别在哪?
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/5069204.html
Copyright © 2020-2023  润新知