美文网首页
集合类型

集合类型

作者: 痴人会说梦 | 来源:发表于2018-03-04 18:42 被阅读13次

    Collection 类型

    Collection Type

    数组(Array),字典(Dictionary),集合(Set),都是以泛型结构体定义的,且不像Objective-c的mutable来表示其可进行修改,而是只有通过var声明的,才能对其进行增删改查,let声明的collection对象不仅不能改变它的值,也不能对其元素做添加,修改,删除等操作.

    数组

    存放相同类型的多个元素的有序线性列表,可以是任意类型,元组也可以,不允许出现不同类型的元素
    数组的声明:
    1.完整声明:Array<Element>,Element表示元素的类型
    2.精简声明:[Element]
    3.数组字面量:[value1,value2..]

    //MARK:数组的声明
    
    //完整声明
    var array = Array<Int>()
    //精简声明
    let r = [Int]()
    
    //5个元素,每一个都是3.0
    let a = [Double](repeating:3.0,count:5)
    let b = [(Int,Double)](repeating: (1,0.5), count: 3)
    
    //数组字面量
    var a1 = [1,2,3,4,5]
    
    //数组不仅可以存放字面量,也可以存放其它常量或者变量
    var a2 = [array,r,[2,3]]
    
    //+操作符 将两个数组拼接在一起
    var sumArr = a1 + [2,67,7]
    sumArr
    
    //通过下标访问操作符访问数组元素
    print("first is \(sumArr[0])")
    
    //下标不可以使用负数,当然你可以自己进行定义
    //超出数组的下标范围,程序会引发异常
    //Fatal error: Index out of range
    //sumArr[-1]
    //sumArr[20]
    
    //下标操作符属于单目后缀操作符,它只有一个操作数。其操作数就是跟在它之前(即左侧)的后缀表达式,而下标中的表达式则不是它的操作数,这点请各位注意。此外,只有遵循了 Collection 协议的类型对象才能作为下标操作符的操作数。
    
    
    //数组包含了多少个元素 Int类型的只读属性
    a1.count
    
    //判断数组是否为空,指的是是否包含元素,而不是是否为空值
    r.isEmpty
    a1.isEmpty
    
    //判断数组是否包含某个元素,返回Bool类型
    a1.contains(1)
    a1.contains(6)
    
    //在最后添加数组元素
    a1.append(6)
    
    //在指定的索引位置插入数组元素
    a1.insert(12, at: 2)
    a1
    
    //删除数组元素(下标)
    a1.remove(at: 1)
    a1
    
    //直接使用数组字面量是一个常量,无法对其进行修改
    
    
    var array1 = [1,2,3,4,5]
    
    print(array1.startIndex)
    print(array1.endIndex)
    
    if let i  = array1.index(of: 30) {
    print(array1[i..<array1.endIndex])
    }
    array1.index(after: 5)
    
    //访问range内的数组元素
    array1[1...3]
    
    //替换range内的元素为传入的collection
    array1.replaceSubrange(1..<3, with: [20,30,40,50])
    print(array1)
    
    //弹出最后一个数组元素
    array1.popLast()
    print(array1)
    
    //并不改变数组的值
    array = Array(array1.dropLast())
    
    print(array1)
    

    集合Set

    集合可以存放多个相同类型的元素
    1.不允许出现相同的元素
    2.无序不能通过下标进行访问
    3.只有遵循Hashable的类型才能作为集合的元素
    String,Int,Double,Float,Bool都遵循该协议

    集合的完整类型Set<Element:Hashable>,Element表示集合元素的类型,没有精简表示法
    也可以通过数组字面量进行创建,但必须通过类型标注申明为Set,否则会被编译器识别为Array

    //创建一个集合类型为<Int>的空集合
    var setA = Set<Int>()
    //或者
    setA = []
    //不定参构造方法
    setA = Set(arrayLiteral: 1,3,4,2,1,3)
    
    //数组字面量
    var setB:Set<Int> = [1,1,2,3,4]
    
    //集合存放对象是根据其哈希值,不是根据下标(无序),所以需要保证存放的元素类型遵循Hashable
    //访问 for-in || flatMap
    for item in setA {
        print(item)
    }
    //元素的个数
    setA.count
    //是都包含元素
    setA.isEmpty
    
    setA.contains(1)
    
    setA.insert(5)
    
    setA.remove(1)
    

    字典

    以键值对的形式存放元素
    特点:无序,键不允许重复,必须遵循Hashable;值可以是任意类型

    完整形式Dictionary<Key:Hashable,Value>,key表示键的类型,value表示值的类型

    精简表示法 [Key:Value]

    //通过默认的构造方法创建一个空字典,类型为[String:Int]
    var a = Dictionary<String,Int>()
    
    //通过字典的不定参构造方法创建一个字典,使用元组来将字典的键值进行捆绑
    //第一个元素为键,第二个元素为值
    a = Dictionary(dictionaryLiteral: ("one",1),("two",2),("three",3))
    
    
    //精简表示法
    let b = [Int:Float]()
    let c = [Int:Float](dictionaryLiteral: (1,1.1),(2,2.22),(3,3.333))
    

    字典字面量

    var a1:[String:Int] = [:]
    
    a1 = ["one":1,"two":2,"three":3]
    

    通过下标操作符进行访问,类型必须为键的类型
    返回的是Optional,不存在就会返回nil

    var a1 = ["one":1,"two":2,"three":3]
    let four = a1["four"]
    let one = a1["one"]
    
    if let f = four {
    print(f)
    }else{
    print("nil")
    }
    
    //根据键修改值
    a1["one"] = 100
    
    //或者根据实例方法,返回原来的值
    a1.updateValue(1, forKey: "one")
    
    //如果key存在就是修改,不存在则意味着新增
    a1["four"] = 4
    
    //根据key删除元素
    a1.removeValue(forKey: "one")
    
    //字典的个数
    a1.count
    
    //是否包含有元素
    a1.isEmpty
    
    
    //keys 属性的类型的是遵循 Collection 与 Equatable 协议的结构体类型;而 values 属性的类型则是遵循 MutableCollection 协议的结构体类型,它们与集合类型类似,不能通过下标方式访问其元素,而一般只能通过 for-in 循环迭代的方式逐一访问
    
    for key in a1.keys{
    print(key)
    }
    
    for value in a1.values {
    print(value)
    }
    

    Range范围操作符

    特点:Range 范围代表的是两个值的区间,它由上下边界进行定义,你可以通过..<来创建一个不包含上边界的半开范围,或者使用...创建同时包含上下边界的闭合范围.
    应用:范围操作符可用于 for-in 循环迭代、获取一个数组的子数组、获取一个字符串的子串、case 语句中的区间匹配等场合

    分别对应下面四种类型

    元素满足
    元素满足 (以整数为步长)

    满足 半开范围 闭合范围
    Comparable Range ClosedRange
    Strideable CountableRange CountableClosedRange
    //Range,CountableRange, ClosedRange, CountableClosedRange
    let emptyRange = 0.0..<0.0
    let singleDigitNumbers = 0..<10
    let lowercaseLetters = Character("a")...Character("z")
    let numbersRange = 1...10
    

    范围操作符的左操作数必须小于等于右操作数,否则将会导致运行时异常
    对于半开区间的范围操作符,如果左操作数等于右操作数,那么该范围是一个空区间
    1.只有半开范围才能表达空区间的概念 (上下边界相等)
    2.只有闭合范围能够包含它的元素类型所能表达的最大值

    如果ClosedRange(闭区间范围操作符)的操作数是一个整数类型,那么该范围操作符的类型将是CountableClosedRange
    如果Range(半开区间范围操作符)的操作数是一个整数类型,那么该范围操作符的类型将是CountableRange
    ClosedRange和Range没有遵循Sequence协议,不能用for-in循环,而CountableRange和CountableClosedRange遵循了Sequence协议,可以用for-in迭代循环

    Countable Range 可数范围 只有这类范围可以被迭代,类型的stride需要用整数进行约束,所以整数和指针类型是这类范围的有效边界值,但是浮点类型不是

    使用

    //for-in迭代循环
    //CountableRange
    for i in 1..<5 {
    print(i)
    }
    
    //CountableClosedRange
    for y in 1...5 {
    print(y)
    }
    
    //如果是浮点数可以使用选择步长的
    for a in stride(from: 4, to: 5, by: 0.1) {
    print(a)
    }
    for b in stride(from: 3, through: 5, by: 0.2){
    print(b)
    }
    
    //Type 'ClosedRange<Character>' does not conform to protocol 'Sequence'
    //for item in lowercaseLetters{
    //
    //}
    
    //获取数组的子数组
    let array = [1,2,3,4,5,6]
    //[3,4,5]
    print(array[2...4])
    
    //获取字符串的子串
    let string = "abcdefghigk"
    let strRange = string.startIndex ..< string.endIndex
    print(string[strRange])
    
    //case区间匹配
    switch 3.0 {
    case 0.0 ..< 2.0:
    print("in 0.0 ..< 2.0")
    case 2.0 ..< 4.0:
    print("in 2.0 ..< 4.0")
    default:
    print("No in range")
    }
    
    //[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    print(singleDigitNumbers.map{$0 * $0})
    

    实例属性与方法

    /// - isEmpty:是否为空
    /// - contains:是否包含某个值
    /// - lowerBound:表示当前范围对象的下边界,一般都是范围操作符左操作数的值。
    /// - upperBound:表示当前对象的上边界。这里无论是闭区间还是半开区间,上边界的值一般都是范围操作符的右操作数的值。
    /// - isEmpty:表示当前范围是否为一个空范围,如果是空范围,那么该属性的值为 true,否则为 false。对于一个闭区间范围而言,它不会存在空范围,所以这个属性必定为 false。
    /// - contains(_:):判断当前范围是否包含了指定的对象。
    /// - overlaps(_:):判断指定的范围是否与当前范围对象存在叠交,只要两者有交集,那么就返回 true,否则为 false
    /// - clamped(to:):裁减当前的范围到指定的区间范围内。
    
    let doubleRange = 1.0 ... 3.0
    
    print(doubleRange.lowerBound)
    print(doubleRange.upperBound)
    
    print("0..<0是否为空\((0..<0).isEmpty)")
    
    print("range has 2.5 :\(doubleRange.contains(2.5))")
    
    print("是否有交集:\(doubleRange.overlaps(2.0..<4.0))")
    
    //裁剪 必须是闭合区间
    let subsRange = doubleRange.clamped(to: 0.5 ... 2.0)
    /// 1.0 ... 2.0
    print(subsRange)
    
    

    单边范围

    单边范围操作符 (partial .部分的,不完全的 ,偏向一方的)
    Swift4.0提供,只对范围操作符的一端设置操作数,另一端缺省
    有三种类型

    1. a... 后缀单目操作符,表示从操作数开始的范围,大于等于a
    2. ...a 前缀单目操作符,表示以操作数为终点的范围,小于等于a
    3. ..<a 前缀单目操作符,表示以操作数为终点的范围,但不包括该数值,即小于a
      注意:操作符必须紧贴操作数
    //CountablePartialRangeFrom
    let countableFrom = 2...
    
    //PartialRangeFrom
    let from = 2.1...
    
    //PartialRangeThrough
    //
    let throughs = ...2
    
    //PartialRangeUpTo
    let upTo = ..<2
    

    使用:获取一个数组的子数组、获取一个字符串的子串

    //使用单边范围获取数组的子数组,字符串的子串
    let array = [1,2,3,4,5]
    //[1,2,3]
    print("...2:\(array[...2])")
    //[3,4,5]
    print("2..:\(array[2...])")
    //[1,2]
    print("..<2:\(array[..<2])")
    
    //获取字符串后五个字符
    let string = "abcdefghigk"
    let strRange = string.index(string.endIndex, offsetBy: -5)...
    print(string[strRange])
    
    

    由于单边范围操作符不能表示一个有限范围的值,因此它不可能遵循Sequence协议,不能使用for-in
    下面是一些方法

    //2
    countableFrom.lowerBound
    
    //2
    throughs.upperBound
    
    //false
    upTo.contains(2)
    

    相关文章

      网友评论

          本文标题:集合类型

          本文链接:https://www.haomeiwen.com/subject/hbdqfftx.html