// 集合类型
// swift 提供 Arrays , Sets 和 Dictionaries 三种基本的集合类型用来存储数据 , 数组(Arrays) 是有序数据的集, 集合(Sets)是无序无重复数据的集, 字典(Dictionaries) 是无序的键值对的集
// swift 语言中的 Arrays, Sets 和 Dictionaries 中存储的数据值类型必须明确, 这意味着我们不能把不正确的数据类型插入其中, 同事这也说明我们完全可以取回值的类型非常自信
// 集合的可变性
// 如果创建一个Arrays , Sets 和 Dictionaries 并且把它分配成一个变量.这个集合将会是可变的.这意味着我们可以在创建之后添加更多或者移除已存在的数据, 或者改变集合中的数据项 , 如果我们把 Arrays , Sets 和 Dictionaries 分配成常量, 那么他就不可变, 他的大小和内容都不能改变
// 在我们不需要改变集合的时候创建不可变集合是很好的实践, swift 的编辑器可以优化我们创建的集合
// 数组
// 数组使用有序列表存储同一个类型的多个值, 相同的值可以多次出现在一个数组的不用位置中
// 注意 : swift 的 Array 类型被桥接到 Foundation 中的NSArray 类
// 数组的简单语法
// 写 swift 数组应该遵循像 Array<Element> 这样的形式, 其中 Element 是这个数组中位置允许存在的数据类型. 我们也可以使用像[Element] 这样的简单语法, 尽管两种形式在功能上一样的, 但是推荐较短的那种, 而且在本文中都会使用这种形式来使用数组
// 创建一个空数组
// 我们可以使用构造语法来创建一个由特定数据类型构成的空数组
var someInts = [Int]()
print("someInts is of type [Int] with \(someInts.count) items")
// 注意 : 通过构造函数的类型, someInts 的值类型被推断为 [Int]
// 或者, 如果代码上下文中已经提供了类型信息, 例如一个函数参数或者一个已经被定义好类型的常量或者变量, 我们可以使用空数组语句创建一个空数组: [] (一对空方括号) :
someInts.append(3)
someInts = []
// 创建一个带有默认值的数组
// swift 中的 Array 类型还提供一个可以创建特定大小并且所有数据都被默认的构造方法, 我们可以把准备加入新数组的数据项数量 (count) 和适当类型的初始值 (repeating) 触感如数组的构造函数:
var threeDoubles = Array(repeating:0.0, count: 3)
// 通过两个数组相加创建一个数组
// 我们可以使用加法操作符 (+) 来组合两种已存在的相同类型数组, 新数组的数据类型会被从两个数组的数据类型中推断出来
var antherThreeDoubles = Array(repeating:2.0, count: 3)
var sixDoubles = Array(repeating:3.0, count: 3)
var sevenDoubles = antherThreeDoubles + sixDoubles
// 用数组字面量构造数组
// 我们可以使用数组字面量来进行数组构造, 这是一种用一个或者多个数值和构造数组的简单方法, 数组字面量是一系列有逗号分隔并由方括号包含的数值
var shoppingList: [String] = ["Eggs","mlik"]
// shoppingList 变量被声明为"字符串值类型的数组", 记作[String], 因为这个数组被规定只有 String 一种数据结构, 所以只有 String 类型可以在其中被存取,
// 在这个例子中, 字面量仅仅包含两个 String 值, 匹配了该数组的变量声明 (只能包含 String 的数组), 所以这个字面量的分配过程可以作为两个初始项来构造shoppingList 的一种方式
// 由于swift 的推断机制, 当我们用字面量构造只拥有相同类型的数值的时候, 我们不必把数组的类型定义清除
// 访问和修改数组
// 我们可以通过数组的方法和属性来访问和修改数组,或者使用下标语法
// 可以使用数组的只读属性count 来获取数组中的数据项数量
print("The shopping list contains \(shoppingList.count) items")
// 使用布尔值属性 isEmpty 作为一个缩写形式去检查 count 属性是否为 0:
if shoppingList.isEmpty{
print("there is a empty array")
}else{
print("there is a true array")
}
// 也可以使用 append(_:) 方法在数组后面添加新的数据项
shoppingList.append("Flour")
// 除此之外, 使用 加法赋值运算符 (+=) 也可以直接在数组后面添加一个或者多个拥有相同类型的数据项
shoppingList += ["baking powder"]
// 可以直接使用下标语法来获取数组中的数据项, 把我们需要的数据项的索引值放在数组名称后面的方括号内
var fiesrItem = shoppingList[0]
// 调用数组的 insert(_at:)方法来在某个具体索引值之前添加数据项
shoppingList.insert("hello", at: 0)
// 如果我们只想把数组中的最后一项移除, 可以使用 removeLast() 方法而不是 remove(_at:)
// 数组的遍历
// 我们可以使用 for-in 循环来遍历所有数组中的数据项
for item in shoppingList {
print(item)
}
// 如果我们同事需要每个数据项的值和索引值, 我们可以使用 enumerated() 方法来进行遍历, enumerated() 返回一个由每一个数据项和数据索引值组成的元组, 我们可以吧这个元组分解成常量和变量来进行遍历
for (index,value) in shoppingList.enumerated() {
print("Item \(value) index:\(index)")
}
// 集合 (Sets)
// 集合(Set) 用来存储相同类型并且没有确定顺序的值, 当集合元素顺序不重要的是或者希望每个元素只出现一次的时候可以使用集合而不是数组
// 注意 : swift 类型被桥接到 foundation 中的 NSSet 类
// 字典
// 字典是一种存储多个相同类型的值的容器, 每个值(value)都关联唯一的键(key),键作为字典中的这个值数据的标识符, 和数组中的数据项不同, 字典中的数据项并没有具体顺序,我们在需要通过标识符访问数据的时候使用字典
// 字典类型简化语法
// swift 的字典使用 dictionary<key,value> 定义, 使用key 是字典中键的数据类型, value 是字典中对应于这些键所存储的数据类型
// 注意 : 我们也可以用[Key: Value]这样简化的形式去创建一个字典类型, 虽然这两种形式功能上相同, 但是后者是首选
// 创建一个空字典
var namesOfIntegers = [Int : String]()
// 如果上下文已经提供了类型信息, 我们可以使用空字典字面量来哦创建一个空字典 记作 [:] (中括号中放一个冒号)
namesOfIntegers[16] = "sixteen"
namesOfIntegers = [:]
// 用字典字面量创建字典
// 我们可以使用字典字面量来构字典, 这和数组字面量构造类似, 字典字面量是一种将一个或多个键值对写作 Dictionary 集合的快捷途径
var airports: [String:String] = ["YYZ":"Toronto Pearson", "DUG":"Dublin"]
// 和数组一样,我们在用字典字面量构造字典时,如果他的键和值都有各自一致的类型,那么久不必写出字典的类型
// 例如 var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
// 访问和修改字典
// 我们可以通过字典的方法和属性来访问和修改字典 , 或者通过使用下标语法
// 通过字典的只读属性 count 来获取某个字典的数据项数量
// 使用布尔值属性 isEmpty 检查 count 属性是否为空
// 可以在字典中使用下标语法来添加新的数据项,
airports["LHR"] = "London"
// 也可以使用下标语法来改变特定键对应的值
airports["LHR"] = "London heathrow"
// 作为另一种下标方法, 字典的 updateValue(_:forKey:) 方法可以设置或者更新特定键对应的值, 这个方法在这个键不存在对应值的时候会设置新值或者在存在的时候更新已存在的值,
// updateValue(_:forKey:) 方法会返回对应值的类型的可选值,举例来说: 对于存储 string 值的字典, 这个函数会返回一个 String? 或者 可选 string 类型的值. 如果有值存在于更新前, 则这个可选值包含了旧值, 否则它将会是nil
if let oldValue = airports.updateValue("Dublin Airport", forKey: "DUB") {
print("The old value for DUB was \(oldValue).")
}
// 我们也可以使用下标语法在字典中安金锁特定键对应的值, 因为有可能请求的键没有对应的值存在,字典的下标访问会返回对应值的类型的可选值, 如果这个字典包含请求键对应的值, 下标会返回一个包含这个存在值的可选值,否则将会返回 nil
if let airportName = airports["DUB"] {
print("The name of the airport is \(airportName).")
} else {
print("That airport is not in the airports dictionary.")
}
// 我们还可以使用下标语法来通过给某个键的对应值赋值为 nil 来从字典中移除一个吧键值对
airports["APL"] = "Apple Internation"
airports["APl"] = nil // APL 被移除了
// 此外, removeValue(forKey:) 方法也可以用来UI出键值对, 这个方法在键值对存在的情况下会移除改键值对, 并且返回被移除的值或者在没有值的情况下返回 nil
if let removedValue = airports.removeValue(forKey: "DUB") {
print("The removed airport‘s name is \(removedValue).")
} else {
print("The airports dictionary does not contain a value for DUB.")
}
//
//字典遍历
//
//我们可以使用for-in循环来遍历某个字典中的键值对。每一个字典中的数据项都以(key, value)元组形式返回,并且我们可以使用临时常量或者变量来分解这些元组:
//
//for (airportCode, airportName) in airports {
// print("\(airportCode): \(airportName)")
//}
//// YYZ: Toronto Pearson
//// LHR: London Heathrow
//更多关于for-in循环的信息,参见For 循环。
//
//通过访问keys或者values属性,我们也可以遍历字典的键或者值:
//
//for airportCode in airports.keys {
// print("Airport code: \(airportCode)")
//}
//// Airport code: YYZ
//// Airport code: LHR
//
//for airportName in airports.values {
// print("Airport name: \(airportName)")
//}
//// Airport name: Toronto Pearson
//// Airport name: London Heathrow
//如果我们只是需要使用某个字典的键集合或者值集合来作为某个接受Array实例的 API 的参数,可以直接使用keys或者values属性构造一个新数组:
//
//let airportCodes = [String](airports.keys)
//// airportCodes 是 ["YYZ", "LHR"]
//
//let airportNames = [String](airports.values)
//// airportNames 是 ["Toronto Pearson", "London Heathrow"]
//Swift 的字典类型是无序集合类型。为了以特定的顺序遍历字典的键或值,可以对字典的keys或values属性使用sorted()方法。