02、Swift3.0中的集合类型

1、Array

1.1 Array的定义

Array表示一组有序的数据集合,有序是指Array中的元素先后的位置关系。

1.1.1 创建一个Array

var array1 : Array<Int> = Array<Int>()
var array2 : [Int] = []
var array3 = array2

1.1.2 创建一个Array同时初始化

var array1 : [Int] = [Int](repeating:1,count:3)
var array2 = array1 + array1
var array3 = [1,2,3,4,5]

1.2 常用属性

1.2.1 获取Array中元素的个数

array3.count

1.2.2 判断Array是否为空

if array3.isEmpty{print("空")}else{print("非空")}

1.2.3 访问Array中的元素

01、通过索引的方式,它是Swift中最不推荐的方式,因为容易崩溃
array3[0] // 1
array3[100] //崩溃

02、访问数组的一个范围
var slice = array3[0...2] // ArraySlice<Int>.Type 
slice = array3[0..<2] // ArraySlice<Int>.Type 
通过上面的方式得到结果并不是数组,而是ArraySlice,Array某一段内容的view
Array(slice)

03、访问数组中最后一个元素
array3.last // Optional<Int>.Type

04、访问数组中的第一个元素
array3.first // Optional<Int>.Type

1.2.4 遍历数组

01、最熟悉的方式
for value in array{print(value)}

02、遍历的时候同时获得Array的索引和值
for (index,value) in array.enumerated(){print("\(index):\(value)")}

03、forEach
array.forEach{print($0)}

1.2.5 添加元素

01、在Array的末尾添加元素
array.append(5) 
array += [5]

02、在Array的中间位置添加元素
array.insert(5, at: 0)

1.2.6 删除元素

array.remove(at: 2)
array.removeLast() //当你删除一个空数组中最后一个元素的时候,会直接引发运行时错误
array.removeFirst()//当你删除一个空数组中第一个元素的时候,会直接引发运行时错误
array.popLast() //数组为空,会返回nil

1.2.7 查找数组中元素的位置

Swift 3.0的写法
a.index { $0 == 1 }

Swift 4.0以及之后的写法
array1.firstIndex(of: 1)
array.firstIndex(where: {$0 == 1})
firstIndex会返回一个Optional<Int>,当要查找的元素存在时,就返回该元素的索引,否则,就返回nil

1.2.8 filter

在Swift中的Collection类型,都有一个filter(:)方法,它接受一个函数作为参数,其目的是对原集合中的元素进行筛选,因此filter(:)的输出结果也是一个数组。
我们可以把Filter想象成一个筛子,只有符合条件的元素才能通过。Filter的关键词是过滤。
用于在Array中,过滤满足特定条件的元素。

func filter(includeElement: (T) -> Bool) -> [T]

var fibonacci = [0,1,1,2,3,5]
let arr = fibonacci.filter{$0 % 2 == 0} //[0,2]

1.2.9 reduce

在Swift中的Collection类型,都有一个reduce(:)方法,它接受一个函数作为参数,其目的是对原集合中的元素进行合并,因此reduce(:)的输出结果也是一个数值。
Reduce最有意思的一点是,他入参函数的第一个参数是上一个的结果值,因此它才有了合并的意义。

func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result
initialResult为初始化的值,也是闭包Result第一次运行的值,Element就是要做处理的元素,处理后返回Result作为下次闭包的参数。

//写法一
fibonacci.reduce(0, +) // 12
//写法二
fibonacci.reduce(0) { x, y in
        x+y
}

1.2.10 map

Swift中的Collection类型,都有一个map(:)方法,它接受一个函数作为参数,其目的是对原集合中的元素进行转换,因此map(:)的输出结果也是一个数组。

func map
(@noescape transform: (Self.Generator.Element) throws -> T) rethrows -> [T]

var fibonacci = [0,1,1,2,3,5]
var mapArr = fibonacci.map{return $0+1} //[1,2,2,3,4,6]

1.2.11 flatMap

flatMap很像map函数,但是它摒弃了那些值为nil的元素。
另外一个与map函数不同之处在于:倘若元素值不为nil情况下,flapMap能够将可选类型(optional)转换为非可选类型(non-optionals)。

let a = 1
var b:Int?
var c = 2
let arr = [a,b,c] // [1,nil,2]
var flatMapArr = arr.flatMap{return $0} //[1,2]
print(flatMapArr)
1.2.12 排序函数:sort和sorted
sort()方法直接改变当前数组。
sorted()方法返回一个当前数组的 copy 排序后返回。

fibonacci.sorted(by: <) //升序
fibonacci.sorted(by: >) //降序
fibonacci.sorted(by:{return $0 < $1}) //升序
1.2.13 获取Array的最大值和最小值
fibonacci.min()
fibonacci.max()

1.3 Array和NSArray的不同

Swift中的Array是按照值语义实现的,当我们复制一个Array对象时,会拷贝整个Array的内容。
Foundation中的NSArray是按照引用语义实现的

1.3.1 按照值语义实现的Array

Swift中的Array是按照值语义实现的,当我们复制一个Array对象时,会拷贝整个Array的内容。

var arr = [1,2,3] // [1,2,3]
let copyArr = arr // [1,2,3]

arr.append(4) 
//arr [1,2,3,4]
//copyArr [1,2,3]

首先,Swift数组是否可以被修改完全是通过varlet关键字来决定的,Array类型自身并不解决它是否可以被修改的问题;

其次,从结果可以看到,复制a并向a添加内容之后,copyArr的内容并不会修改。但是,Swift在复制Array时,同样对Array的性能有所考量,它使用了copy on write的方式。即如果你仅仅复制了Array而不对它修改时,真正的复制是不会发生的,两个数组仍旧引用同一个内存地址。只有当你修改了其中一个Array的内容时,才会真正让两个Array对象分开。

1.3.2 按引用语义实现的NSArray

在Foundation中,数组这个类型有两点和Swift Array是不同的:

数组是否可以被修改是通过NSArrayNSMutableArray这两个类型来决定的;
NSArrayNSMutableArray都是类对象,复制它们执行的是引用语义;

但是当把Swift中的letvarFoundation中的NSArrayNSMutableArray放在一起使用时就会出现一些奇特的表现。

let mutableArr = NSMutableArray(array: [1,2,3]) //[1,2,3]

let copyB : NSArray = mutableArr //[1,2,3]

mutableArr.insert(0, at: 0) // [0,1,2,3]
copyB //[0,1,2,3]

创建mutableArr使用了可修改数组NSMutableArray,创建copyB时使用的是不可修改数组NSArray,而赋值的时候是引用拷贝,实际上copyB和mutableArr指向了同一块内容空间。当我们去修改mutableArr时,copyB也收到了影响。

为了拷贝NSArray对象时,执行值语义,我们必须使用它的copy方法复制所有的元素:

let mutableArr = NSMutableArray(array: [1,2,3]) // [1,2,3]
let deepCopy : NSArray = mutableArr .copy() as! NSArray //[1,2,3]
mutableArr.insert(0, at: 0) // [0,1,2,3]
deepCopy //[1,2,3]

当我们使用NSArray和NSMutableArray时,Swift中的var和let关键字就和数组是否可以被修改没关系了。它们只控制对应的变量是否可以被赋值成新的NSArray或NSMutableArray对象。

2、Dictionary

Dictionary是除了Array之外的另一种非常重要的数据结构,它用于把某种形式的key,关联到某种形式的value,它是一个无序集合。

2.1 定义Dictionary

let dic = ["name":"lichangan","age":18,"sex":"male"] as [String : Any]
let name = dic["name"]
[]用在Dictionary的时候,会返回一个Optional类型来确保这种形式的访问安全。因此,访问不存在的key,并不会导致运行时错误。

2.2 常用基本属性

2.2.1 获取元素个数
dic.count
2.2.2 判断是否为空
dic.isEmpty
2.2.3 访问一个Dictionary的所有keys
dic.keys
2.2.4 访问一个Dictionary的所有values
dic.values
2.2.5 添加、更新和删除元素
//01、当我们复制Dictionary对象的时候,就会拷贝Dictionary中的所有内容。
dic = dic1
//02、使用key就可以访问和修改Dictionary的内容
dic["age"] = 19

//03、如果我们希望更新value的时候,同时获得修改前的值,还可以使用updateValue(_:forKey:)方法:
let oldValue = dic.updateValue(20, forKey: "age")

//04、当我们要在Dictionary中添加元素时,直接给要添加的key赋值就好了:
dic["isMarriage"] = true

//05、当我们要删除特定的key时,直接把它的值设置为nil
dic["isMarriage"] = nil

这里,并不是把特定key的值设置为nil(毕竟Dictionary中value部分的类型也不是optional),而是删除特定的key。当某个key的value被设置成nil后,这个key也就从Dictionary中删除了。
2.2.6 遍历Dictionary
for (k,v) in dic {print("\(k),\(v)")}
dic.forEach{print("\($0),\($1)")}

//由于Dictionary是一个无序集合(unordered collection),因此当我们编辑了Dictionary之后,每次遍历,访问元素的顺序都可能是不同的。如果我们希望按照固定的顺序来访问Dictionary中的元素,一个最简单的办法,就是对key排序后,再进行遍历

for key in dic.keys.sorted() {
    print(dic[key])
}

//本质上来说,Dictionary是一个哈希表,它所有的key都用各自的哈希值保存在一个数组里。因此,通过key在Dictionary中访问value是一个O(1)操作。但这也对key的类型做出了一个要求,它必须可以计算哈希值。Swift标准库中提供的绝大多数类型,例如:Int / Float / Double / String / Bool / Date ...等,都满足这个要求,因此我们可以直接拿它们来定义Dictionary。

3、Set

除了Dictionary之外,Set是Swift标准库中,另外一个主要的无序集合(unordered collection)类型,包含一组不重复的值。你也可以把Set理解为一个只包含key而没有value的集合。本质上,Set也是一个哈希表,因此它有着和Dictionary诸多类似的地方。

3.1 定义Set

var vowel: Set<Character> = ["a", "e", "i", "o", "u"]
// var vowel: Set = ["a", "e", "i", "o", "u"]

3.2 Set的常用属性和方法

3.2.1 获取元素个数
vowel.count
3.2.2 判断是否为空
vowel.isEmpty
3.2.3 是否包含某个元素
vowel.contains("a")
3.2.4 移除某个元素
vowel.remove("a")
3.2.5 插入某个元素
vowel.insert("a")
3.2.6 清空
vowel.removeAll()
3.2.7 遍历
for character in vowel {print(character)}
vowel.forEach{print($0)}

//当我们每次遍历Set时,遍历的顺序,都会根据当前Set包含的值而有所不同。如果你希望按照某种“固定”的排序方式访问Set中的元素,就要使用它的sorted方法:
for character in vowel.sorted(){print(character)}

3.3 Set代数运算

var setA:Set = [1,2,3,4,5,6]
var setB:Set = [4,5,6,7,8,9]
3.3.1 交集

交集,指的是两个集合之间都有的部分

let interSectAB:Set = setA.intersection(setB)
3.3.2 并集

并集,两个集合的元素都算上,就是最后的并集。

let unionAB:Set = setA.union(setB)
3.3.3 对称差集

对称差集,集合A与集合B的对称差集定义为集合A与集合B中所有不属于A∩B的元素的集合

let symmetricDiffAB:Set = setA.symmetricDifference(setB)
3.3.4 差集

差集:所有属于A且不属于B的元素的集合被称为A与B的差

let aSubstractB:Set = setA.subtracting(setB)
3.3.5

除此之外,上面这些API还有一个“可修改Set自身”的版本,而命名方式,就是在这些API的名称前面,加上form,例如:

setA.formIntersection(setB) // { 5, 6, 4 }

这样,setA的值,就被修改成了取交集之后的值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值