swift资源库—3—字典/集合/数组

Posted 3行代码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了swift资源库—3—字典/集合/数组相关的知识,希望对你有一定的参考价值。

持续更新中~~

转载注明 http://blog.csdn.net/jiang314

前言

Swift语言提供Array、Set和Dictionary三种基本的集合类型用来存储集合数据。数组是有序的数据集;集合是无序无重复的数据集;而字典是无序的键值对数组集。

image

Swift的Array、Set和Dictionary类型被实现为泛型集合。因此,它所存储的元素的类型必须是一致的,同样,我们取出来的数据类型也是明确的。

集合的可变性

如果创建一个Arrays、Sets或Dictionaries并且把它分配成一个变量,这个集合将会是可变的。这意味着我们可以在创建之后添加更多或移除已存在的数据项,或者改变集合中的数据项。

如果我们把Arrays、Sets或Dictionaries分配成常量,那么它就是不可变的,它的大小和内容都不能被改变。

若我们确定集合不需要改变,那么我们应该使用不可变集合,也就是使用let声明,那样编译器会为我们优化。

// 在swift中要让Array、Set、Dictionary类型的变量是可变的,用var声明就可以了。
// 如果不希望可变,用let声明即可。
let immutableArrray = [Int]()

// 提示:error: immutable value of type '[Int]' only has mutating
// members named 'append'
//immutableArrray.append(12)

// OK
var mutableArray = [Int]()
mutableArray.append(12)

我的博客:http://blog.csdn.net/jiang314


数组

数组使用有序列表存储同一类型的多个值,相同的值可以多次出现在一个数组的不同位置中。我们需要明确,数组是有序的,元素类型是相同的。

Swift中的Array与Foundation中的NSArray是桥接的,可以相互转换。

1、创建一个空数组

由于Swift中的数组是泛型,因此必须指定元素的数据类型:

//1、创建空数组
    
    //定义数组只能保存字符串
    var array:[String]
    //定义数组只能保存int
    var arrint = [Int]()
    //定义数组,使用结构体Array的构造写法
    var anotherEmptyArray = Array<Int>()


2、创建带默认值的数组

Swift提供了如下方法,可以创建带有默认值的数组,这个构造方法是使用count个指定元素来初始化:

//2、创建带默认值得数组
    // threeDoubles 是一种 [Double] 数组,等价于 [1.0, 1.0, 1.0]
    var threeDoubles = [Double](count: 3, repeatedValue:1.0)

3、数组相加来创建数组

两个数组能够通过加号+来创建一个合并的数组,是因为苹果为我们提供了这样的方法:

//3、数组相加 来创建数组
    //要求:遵守RRC协议 ; 两个集合的元素类型要求相同
    //数组是遵守RRC协议的.
    // anotherThreeDoubles 被推断为 [Double],等价于 [2.5, 2.5, 2.5]
    var anotherThreeDoubles = Array(count: 3, repeatedValue: 2.5)
    // sixDoubles 被推断为 [Double],等价于 [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]
    var sixDoubles = threeDoubles + anotherThreeDoubles

4、实例构造数组

我们可以使用字面量数组来进行数组构造,这是一种用一个或者多个数值构造数组的简单方法。字面量是一系列由逗号分割并由方括号包含的数值:

//4、创建实例数组
    // shoppingList 已经被构造并且拥有两个初始项。
    var shoppingList: [String] = ["Eggs", "Milk"]
    // 由于类型是明确的,因此我们可以交由编译器来推断类型数组的类型:
    var shoppingListt = ["Eggs", "Milk"]


5、访问和修改数组

常见的数组访问和修改操作有:

  • 获取数组元素个数
  • 判断数组是否为空
  • 数组追加元素
  • 数组在某个位置插入元素
  • 数组在某个范围插入元素

5.1 数组元素个数

获取数组元素的个数,可通过count属性获取:

print("The shopping list contains \\(shoppingList.count) items.")

5.2 数组判断是否为空

判断数组是否为空,可以通过isEmpty属性判断,也可以通过count判断:

if shoppingList.isEmpty {
    print("The shopping list is empty.")
} else {
    print("The shopping list is not empty.")
}

// 或者通过count属性
if shoppingList.count == 0 {
    print("The shopping list is empty.")
} else {
    print("The shopping list is not empty.")
}

5.3 数组末尾追加元素

常用的有以下几种方法:

  • 通过append()追加
  • 通过appendContentsOf()追加
  • 通过+=追加

//末尾追加:通过append()追加;通过appendContentsOf()追加;通过+=追加
    var array21 = [1, 2]
    // 追加单个元素
    array21.append(3)
    // 追加一个数组
    array21 += [4, 5]
    // 追加一个集合
    array21.appendContentsOf([6, 7])
    // 追加一个序列:1,2,3,4,5,6.  要求数组为INT类型
    array21.appendContentsOf(1...6)

5.4 数组插入元素

数组提供了insert(_:at:)方法插入数据:

array21.insert(121, atIndex: 2)

5.5 数组修改值

我们也可以通过下标获取或者修改数据,我们先看看声明:

//数组修改值:
    // 下标
    array21[0] = 100; print(array21[0])
    // 可以修改指定范围的值
    array21[1..<4] = [77, 88, 99]; print(array21[1..<4])
    // replaceRange(_:with:)来替换值:
    array21.replaceRange(1...2, with: [10, 12])

5.6 数组移除元素

先看看苹果所提供的方法:

// 删除第一个
    let element = array.removeAtIndex(0)
    // 删除最后一个
    let lastElement = array.removeLast()
    // 删除所有元素,但是内存不释放,空间容量保留
    array.removeAll(keepCapacity: true)
    // 删除所有元素,且不保留原来的空间
    array.removeAll(keepCapacity: false)
    // 移除位置1、2、3的元素
    array.removeRange(1...3)
    // 移除第一个元素
    let first = array.removeFirst()
    // 移除前三个元素
    array.removeFirst(3)


5.7 数组遍历

常用的数组遍历有几种。

// 第一种,只获取元素值 :
    for item in array {
        print(item)
    }
    // 第二种,获取元素值及索引:
    for (index, value) in array.enumerate() {
        print("index: \\(index), value = \\(value)")
    }

我的博客:http://blog.csdn.net/jiang314


集合

集合(Set)用来存储相同类型并且没有确定顺序的值。当集合元素顺序不重要时或者希望确保每个元素只出现一次时可以使用集合而不是数组。

为了存储在集合中,该类型必须是可哈希化的。也就是说,该类型必须提供一个方法来计算它的哈希值。一个哈希值是Int类型的,它和其他的对象相同,其被用来比较相等与否,比如a==b,它遵循的是a.hashValue == b.hashValue。Swift 的所有基本类型(比如String,Int,Double和Bool)默认都是可哈希化的,它可以作为集合的值或者字典的键值类型。没有关联值的枚举成员值(在枚举有讲述)默认也是可哈希化的。

使用自定义的类型作为集合的值或者是字典的键值类型时,需要使自定义类型服从Swift标准库中的Hashable协议。服从Hashable协议的类型需要提供一个类型为Int的取值访问器属性hashValue。这个由类型的hashValue返回的值不需要在同一程序的不同执行周期或者不同程序之间保持相同。 因为hashable协议服从于Equatable协议,所以遵循该协议的类型也必须提供一个”是否等”运算符(\\==)的实现。这个Equatable协议需要任何遵循的\\==的实现都是一种相等的关系。也就是说,对于a,b,c三个值来说,\\==的实现必须满足下面三种情况:

  • a\\==a(自反性)
  • a\\==b 可推出 b\\==a(对称性)
  • a\\==b&&b\\==c 可推出 a\\==c(传递性)

1、空集合

Swift中的Set类型被写为Set<Element>,这里的Element表示Set中允许存储的类型,和数组不同的是,集合没有等价的简化形式。

//1 空集合
    var emptySet = Set<Int>()
    print(emptySet.count) // 0
    // 当变量已经有明确的类型时,再用空数组来初始化[],其类型也是可推断的
    emptySet = []// 类型为Set<Int>()

2、初始化集合(Initializing An Empty Set)

可以直接使用数组字面量来初始化集合:

// 2、初始化集合
    var favSet:Set<String> = ["mi","wer"]
    var fwas:Set  = ["we","sdsv"]
    var asss:Set<String> = ["as","sd","as","sd"]//重复的as,sd会自动删除

3、访问集合(Accessing A Set)

获取集合元素的个数,可以通过count只读属性获取,其时间复杂度为O(1),也就是常量,因此效率是极高的。想想时间复杂度能达到O(1),说明内部并不是列表,而是类似字典那样的哈希表,不过具体内部是如何,这里不细说,还得去查看源代码才能知晓。

//3 访问集合
    //获取个数   可以通过count只读属性获取,其时间复杂度为O(1),也就是常量,因此效率是极高的
    //public var count: Int { get }
    let count = asss.count
    // 判断是否为空集:isEmpty属性判断是否为空:
    if favSet.isEmpty {
        print("empty set")
    } else {
        print("non empty set")
    }
    // 判断是否包含元素
    if favSet.contains("wahaha") {
        print("fav set contains wahaha")
    } else {
        print("fav set doesn\\'t not contain wahaha")

    }

4、遍历集合(Iterating Over A Set)

遍历很少能离开得了for-in语法

//4.1遍历一个set。使用for-in

    for value in favSet {
        print(value)// 这是无序的
    }
    // 4.2遍历集合,同时使之有序
    // sort方法
    for value in favSet.sort({ (e, ee) -> Bool in
        return e > ee // 由我们指定排序类型desc(降序)
    }) {
        print(value)// mikl egg
    }
    // 4.3或者直接使用sort无参数(默认为asc升序)
    for value in favSet.sort() {
        print(value)// egg   milk
    }
    // 4.4当然还可以使用最原始的方法来遍历:
    for var i = favSet.startIndex; i != favSet.endIndex; i = i.successor() {
        print("for-i-in" + favSet[i])
    }

5、集合基本操作(Fundamental Set Operations)

集合的基本操作有:

  • 求交集:使用intersect(_:)方法根据两个集合中都包含的值创建的一个新的集合。
  • 求非交集:使用exclusiveOr(_:)方法根据在一个集合中但不在两个集合中的值创建一个新的集合。
  • 求并集:使用union(_:)方法根据两个集合的值创建一个新的集合。
  • 求差集:使用subtract(_:)方法根据不在该集合中的值创建一个新的集合。

image

/** 5、集合基本操作
     求交集:使用 a intersect(b) 方法根据两个集合中都包含的值创建的一个新的集合 (ab的交集)。
     求非交集:使用 a exclusiveOr(b)方法根据在一个集合中但不在两个集合中的值创建一个新的集合(ab并集减去交集的集合)。
     求并集:使用 a union(b)方法根据两个集合的值创建一个新的集合 (ab并集)。
     求差集:使用 a subtract(b)方法根据不在该集合中的值创建一个新的集合(a中非b的集合)。
     */
    let set11: Set = [1, 2, 3, 4, 5]
    let set21: Set = [1, 3, 4, 8]
    
    // 求两个集合的交集
    // 1, 3, 4
    print(set11.intersect(set21))
    
    // 求两个集合的并集
    // 1, 2, 3, 4, 5,8
    print(set11.union(set21).sort())
    
    // 求集合set1去掉set1与set2的交集部分
    // 2, 5
    print(set11.subtract(set21).sort())
    
    // 求集合set1与set2的并集 去掉 集合set1与set2的交集 部分
    // 2, 5, 8
    print(set11.exclusiveOr(set21).sort())

6、集合成员关系(Relationships Of Set members)

  • 使用\\==来判断两个集合是否包含全部相同的值。
  • 使用isSubsetOf(_:)方法来判断是否为子集
  • 使用isSupersetOf(_:)方法来判断是否为超集
  • 使用isStrictSubsetOf(_:)或者isStrictSupersetOf(_:)方法来判断一个集合是否是另外一个集合的子集合或者父集合并且两个集合并不相等。
  • 使用isDisjointWith(_:)方法来判断两个集合是否不含有相同的值。

image

从图中可以看出:

  1. 集合a全部包含b,也就是说b是a的子集
  2. 集合a与集合b相交,但是a与b不完全包含
  3. 集合c与集合b完全没有交集

let set1: Set = [1, 2, 3, 4, 5]
    let set2: Set = [1, 3, 4, 8]
    // set1并没有全部被set2包含
    print(set1.isSubsetOf(set2))// false
    
    let set3: Set = [1, 2, 5]
    // set3全部在set1中
    print(set3.isSubsetOf(set1))// true
    
    // set1真包含set3,因此set1是set3的超集
    print(set1.isSupersetOf(set3))// true
    
    // set1是set3的严格超集,因为Set1真包含set3且set1 != set3
    print(set1.isStrictSupersetOf(set3))// true
    
    // set1真包含set3,且set1 != set3,因此set3是set1严格的真子集
    print(set3.isStrictSubsetOf(set1))// true
    
    let set4: Set = [1, 5, 2]
    // 因为set3和set4的元素是一样的,即相等
    print(set4.isStrictSubsetOf(set3))// false
    
    // 这两个集合中有相同的元素
    print(set3.isDisjointWith(set4))// false
    
    let set5:Set = [9, 6]
    // set5和set4没有相同的元素
    print(set5.isDisjointWith(set4))// true

我的博客:http://blog.csdn.net/jiang314

字典

字典是一种存储多个相同类型的值的容器。每个值都关联唯一的键,键作为字典中的这个值数据的标识符。和数组中的数据项不同,字典中的数据项并没有顺序的。我们在需要通过key访问数据的时候使用字典,这种方法很大程度上和我们在现实世界中使用字典查字义的方法一样。

Swift中的Dictionary与Foundation中的NSDictionary是桥接的,可以互相转换使用。

它是基于哈希表从key到value实例的映射,它的键值是无序的。要求key是遵守Hashable的。
其正规语法应该是:Dictonary<key, value>

1、创建空字典

// 1、创建空字典
    var emptyDict = [Int: String]()
    // 或者
    emptyDict = Dictionary<Int, String>()
    // 当创建过emptyDict后,再用[:]又成为一个空字典
    emptyDict = [:]

2、初始化字典

//2、初始化字典(Initializing A Dictionary)
    
    // 多个键值对用逗号分割
    // 通过类型推断是可以推断出来类型为[String: String]
    var dict = ["A": "Apple", "B": "Bubble"]
    // 手动指明数据类型
    var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
    
    //声明不可变字典:
    // 如果不希望字典可变,用let声明即可
    let immutableDict = ["A": "Apple", "B": "Bubble"]
    // 无法调用,因为是不可变的
    //immutableDict.updateValue("App", forKey: "A")
    //immutableDict += ["AB:", "Apple Bubble"]

3、访问和修改字典

我们可以通过字典的方法和属性来访问和修改字典,或者通过使用下标语法。

// 3、访问和修改字典
    
    // 我们可以通过字典的方法和属性来访问和修改字典,或者通过使用下标语法。
    // 3.1 判断是否为空字典:
    
    if dict.isEmpty {
        print("dict is an empty dictionary")
    } else {
        print("dict is not an empty dictionary")
    }
    // 或者通过获取字典元素的个数是否为0
    if dict.count == 0 {
        print("dict is an empty dictionary")
    } else {
        print("dict is not an empty dictionary")
    }
    
    // 3.2 可以直接通过下标获取元素:
    // 通过key直接获取
    var apple = dict["A"]
    
    // 获取索引获取(key, value),再获取值
    // 由于字典中的(key, value)是元组,因此可以直接通过点语法获取
    let startKeyValue = dict[dict.startIndex]//第一个键值对
    let value = startKeyValue.1//值
    
    // 3.3 读取时,判断是否有值
    if let value = dict["BB"] {
        print("value is \\(value)")
    } else {// 输入这行
        print("The key BB doesn\\'t not exist in dict")
    }
    
    // 3.4 可以直接通过下标来修改或者增加值:
    // 修改,如果不存在,则会增加,否则更新值
    dict["A"] = "Good Apple"
    
    // 或者用API,如果不存在,则会增加,否则只是更新值
    if let oldValue = dict.updateValue("Dog", forKey: "D") {
        print("The old value is \\(oldValue)")
    } else {
        // 输出这行
        print("The key D does\\'t not exist before update")
    }
    
    // 3.5 移除元素:
    // 通过下标语法移除元素
    dict["D"] = nil
    // 或者通过调用removeValueForKey方法来移除
    if let removedValue = dict.removeValueForKey("D") {
        print("The removed value is \\(removedValue)")
    } else {
        print("The key D doesn'\\t exist in dict, can\\' be removed.")
    }
    // 或者清空字典:
    dict.removeAll()

4、字典遍历

// 4 字典遍历(Iterate Over A Dictionary)
    // 字典中每个元素是一个键值对,而这个键值对其实就是一个元组:
    // 用for-in遍历,形式为(key, value)
    for (key, value) in dict {
        print("\\(key): \\(value)")
    }
    // 可以通过遍历所有的key:
    for key in dict.keys {
        print("\\(key): \\(dict[key])")
    }
    // 也可以遍历所有的值:
    for value in dict.values {
        print("\\(value)")
    }


5、字典值或者键转换成数组

将字典的key或者value转成数组:

    // 获取所有的值
    let values = [String](dict.values)
    
    // 获取所有的键
    let keys = [String](dict.keys)

我的博客:http://blog.csdn.net/jiang314


最后:

本篇博文是笔者在学习Swift 2.1的过程中记录下来的,同时参考了标哥的博客,在此一并感谢。


分享一些swift学习的资料,和大家一块学习,有啥问题还请留言哦~~



以上是关于swift资源库—3—字典/集合/数组的主要内容,如果未能解决你的问题,请参考以下文章

Swift快速入门集合

访问字典数组 Swift 3

Swift - 啥决定了字典集合的顺序?

使用日期 Swift 3 对字典数组进行排序

如何在swift 3中从字典中获取数组

Swift-2.4集合类型