1. Swift集合的基本概况:
1) 简化了集合的种类,只包含数组Array和字典Dictionary两种集合,前者管理单值集合后者管理双值集合(键-值类型);
2) 在Swift中仍然可以使用Cocoa Library中的集合类,如NSDictionary、NSArray等,但应尽可能避免使用这些类,因为Swift内置的Array和Dictionary功能更强大,并提供了强大的错误校验机制;
2. 数组:
1) 和C语言和Java中的数组不一样,功能更加强大,可以进行增删改等操作,效率非常高,是普通数组和List的结合体;
2) 但Swift的数组并没有和Python那样,数组元素的类型可以互不相同,Swift的数组还是要求类型要保持一致的,从数组的定义来看(使用[]和,作为元素分隔符):
let let_arr: Array<String> = ["abc", "def"] // 利用泛型定义字符串数组
let_arr = ["abc"] // Bad! 常量数组不能修改数组本身
let_arr[1] = "kfc" // Bad! 常量数组同样不可以改变元素值
var var_arr: [String] = ["abc", "def"] // 利用数组的类型名来定义字符串数组
var_arr = ["k", "fg", "qqq"] // OK! 变量数组可以随意改
var_arr[1] = "ppp" // OK!
// 以上可以将Array<String>和[String]可以看做一种类型名,就叫做字符串数组类型
// 同样[Int]就是整型数组类型,就和类型名String、Double、Int等一样
也可以根据类型推断数组类型:
let arr = ["abc", "bcd"] // 数组中的类型必须一致!推断出是[String]类型
3) 数组类型的未初始化问题:[Type]本身就是一种类型,可以当做Int、String等类型看待,普通数据未初始化是不能使用的,即使是println里面也不能使用,除非是定义为可选类型,比如[Type]?,这样在未初始化时为nil,至少println里面还是可以使用的:
var arr1: [Int]
println(arr1) // Bad! 未初始化不得使用
var arr2: [Int]?
println(arr2) // OK! nil
4) 创建空数组:初始化时往往要求数组为空,有两种方法,一种是调用[Type]类的构造函数,另一种是用一个真正意义上的空数组[]赋值给数组变量或常量
var arr1 = [Int]() // 采用类型推断,[Int]类型的构造函数,空的参数表示一个空数组
var arr2: [Int] = [Int]() // 更加具体了
var arr3: [Int] = [] // 赋值一个空数组,但是必须指定数组类型,否则无法推断数组类型
var arr4: Array<Int> = [] // 原理相同
!!没有初始化就不会在内存中开辟空间,如果初始化了(即使是创建了一个空的数组),在内存中还是为其开辟空间的,不仅对于数组,对于任何类型的数据来说都是一样的!
5) 如果数组内元素的类型不一致怎么办?
只有在使用类型推断初始化时才会发生:
var arr = ["abc", 123, 234.323] // 其实使用Cocoa的NSMutableArray来实现的,元素类型为抽象类型NSObject
arr = ["df"] // 可以改变数组本身
println(arr)
arr.append(23.422) // 可以追加
println(arr)
arr[1] = 72.234 // 可以修改数组元素
println(arr)
arr += ["xxdlfsd", 234.23, 9299320] // 可以追加任意数组,由类型推断用Swfit的Array包装了NSMutableArray
println(arr)
var arr_empty = [] // 由于类型无法推导,所以还是使用NSMutableArray来实现
如果定义数组变量或常量的时候指定了类型[Type],但是初始化时数组中元素的类型不一致或者和Type指定的不一样,编译器会直接报错!
6) 创建固定长度的数组以及规定默认的初始化值:有时需要使用类似C语言那样限制长度的传统数组,这是就需要使用数组类型的构造函数,并制定相关的参数达到上述目的
// 这里必须同时指定数组长度和默认初始化值,少一个都不行!
var arr = [Int](count: 4, repeatedValue: 2)
println(arr.count) // 4
println(arr) // [2, 2, 2, 2]
7) 访问数组元素:和C语言一样,通过arrayname[index]的方式访问,其中let定义的常量数组的值不可修改,而var定义的变量数组可以;
8) 数组的连接——使用+运算符:
var arr1 = ["abc", "bcd"]
var arr2 = ["xxx", "yyy"]
println(arr1 + arr2) // [abc, bcd, xxx, yyy]
//var arr3 = arr1 + "ppp" // Bad! 数组的+运算的两个操作数必须都是数组类型的
//var arr3 = arr1 + [23, 123] // Bad! 必须是两个元素类型完全相同的数组才能相连接
arr1 += arr2 // +=在连接的同时也改变了arr1
println(arr1) // [abc, bcd, xxx, yyy]
println(arr1 += arr2) // Not so good! +=不返回任何值,因此这里什么都不输出,仅仅是输出一个空行,虽然不会编译错误!)
arr1 += "hahaha" // Bad! +=同样也是连接运算符,也要求左右两个操作数都是数组类型的!
9) 数组的修改:
var arr = ["aaa", "bbb"]
// 在数组末尾追加一个元素
// 注意,只能追加一个,即一个一个追加,不能一次追加多个
// 注意和+和+=的区别,它们俩作用的必须是数组,即使追加一个也必须是arr += ["ccc"]
// .append的参数是数组中的元素而不是数组,参数的类型必须是元素的类型
arr.append("ccc")
println(arr) // [aaa, bbb, ccc]
// 在指定下标出插入一个元素
// 从该下标处开始往后的所有元素都往后挪一个位置
arr.insert("AAA", atIndex: 1)
println(arr) // [aaa, AAA, bbb, ccc]
// 删除最后一个元素
arr.removeLast()
println(arr) // [aaa, AAA, bbb]
// 删除指定下标的元素
arr.removeAtIndex(1)
println(arr) // [aaa, bbb]
// 清空所有元素
// 需要指定内存空间是否要保留,如果为false则会清空成最小(只保留信息标记补保留数据空间)
arr.removeAll(keepCapacity: true)
println(arr) // []
println(arr.count) // 0,返回当前数组元素个数
println(arr.isEmpty) // true,返回数组当前是否为空
!!对于以上使用到索引值的,如果索引越界都会抛出运行时异常,并可以直接定位到出错误的索引处,因此非常安全!
10) 数组的遍历:一共有三种方式,分别为枚举下标、枚举元素、同时枚举下标和元素
let names = ["小红", "小白", "小花"]
// 枚举下标
for i in 0..<names.count
{
println("数组索引:\(i),数组元素:\(names[i])")
}
// 枚举元素
var i = 0
for name in names
{
println("数组索引:\(i),数组元素:\(names[i])")
i++
}
// 同时枚举下标和元素
// 使用全局函数enumerate获取数组索引和元素的结构体,并将该结构体存放在元素(index, value)中并分解
for (index, value) in enumerate(names)
{
println("数组索引:\(index),数组元素:\(value)")
}
11) 区间赋值:
i) 支持闭区间和半开半闭区间两种:
arr[min...max] = [item1, item2, ...]
arr[min..<max] = [item1, item2, ...]
var arr = [1, 2, 3, 4, 5, 6]
arr[0...2] = [7, 7, 7]
println(arr) // [7, 7, 7, 4, 5, 6]<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
ii) 异常情况:
min、max越界:运行时抛出异常
var arr = ["a", "b", "c", "d"]
// 赋值个数超出指定的区间
// 超出数组范围,则在数组末尾追加
arr[2...3] = ["x", "y", "z"]
println(arr) // [a, b, x, y, z],在末尾追加了一个‘z'
// 未超出数组返回,但是arr[max]后面还有元素,则插入
arr[2...3] = ["x", "y", "q"]
println(arr) // [a, b, x, y, q, z],'z'的前面插了一个'q'
// 赋值的个数小于指定的区间范围,则会删除指定区间中多余的元素
arr[0...5] = ["p", "q", "r"]
println(arr) // [p, q, r],后面三个直接被删除了