Swift中提供了三种基本的集合类型来存储集合数据:
- 数组(Arrays) 有序的数据的集
- 集合(Sets) 无序无重复的数据集
- 字典(Dictionaries) 无序的键值对值
Swift中
Arrays
、Sets
和Dictionaries
,这意味着我们不能把不正确的数据类型插入其中.同时这也说明我们完全可以对取回值的类型非常自信.
集合的可变性
Swift中Arrays
、Sets
和Dictionaries
被var 和let 修饰的生活,和其他类型的数据的原理是一样的,var 修饰的时候,是变量,可修改他们里面的值,let 修饰的时候,是常量,常量不可变.
Arrays
//数组使用有序列表存储同一类型的多个值。相同的值可以多次出现在一个数组的不同位置中.
//这个与OC中的数组的概念有点不一样,OC中的数组可以存放不同类型的对象,但是不能存放基础类型
//如何定义一个包含Int 类型的数组
var intItems = [Int]() //中括号,包含一个类型,然后接一个小括号
intItems.append()
someInts.append(1)
someInts.append(2)
//someInts.append("a")//这个写法编译出错
print(someInts) // [1 ,2]
//因为上面再定义数组intItems是指定了它只能存放Int类型,
//所以在调用Arrays的.append()方法时系统也会提示只能放入Int类型的值
创建一个带有默认值的Array
//创建一个简单的 Int 类型 常量数组
let array = [1,2]
print(array) // [1,2]
//创建一个简单的Double 类型 变量数组
var threeDoubles = Array(repeating: 0.0, count: 3)
print(threeDoubles) //[0.0, 0.0, 0.0]
//通过两个数组相加得到另外一个数组
var anotherThreeDoubles = Array(repeating: 2.5, count: 3)//[2.5, 2.5, 2.5]
var sixDoubles = threeDoubles + anotherThreeDoubles
//sixDoubles 等于 [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]
访问和修改数组
var shoppintList = ["苹果","土豆","鸡肉","牛肉"]
//通过.count属性获得数组的元素个数
print("shoppingList contain \(shoppintList.count) items")
//输出 :shoppingList contain 4 items
//判断数组是否为空
if shoppingList.isEmpty {
print("YES")
}else{
print ( "NO" )
}//输出结果 NO
//使用.append()方法追加元素
shoppintList.append("鸭肉")
//此时shoppintList等于["苹果", "土豆", "鸡肉", "牛肉", "鸭肉"]
//使用 += 运算符在变量数组后追加另外一个数组
shoppingList += ["青菜","乌龟"]
//此时shoppintList等于["苹果", "土豆", "鸡肉", "牛肉", "鸭肉","青菜","乌龟"]
//使用数组的下标来访问数值中的元素,与OC的使用方法一样
let firstItem = shoppingList[0] //这里firstItem会被判定为String类型
print(firstItem) //输出 "苹果"
//使用下标来改变数组中对应的值
shoppingList[0] = "鸡蛋"
//此时shoppingList 等于 ["鸡蛋", "土豆", "鸡肉", "牛肉", "鸭肉","青菜","乌龟"]
//insert(_:at:)方法插入一个元素
shoppintList.insert("苹果", at: 0)
//此时shoppintList等于 ["苹果","鸡蛋", "土豆", "鸡肉", "牛肉", "鸭肉","青菜","乌龟"]
//remove(at: )方法删除一个元素
shoppingList.remove(at: 7)
print(shoppingList)//["苹果", "鸡蛋", "土豆", "鸡肉", "牛肉", "鸭肉", "青菜"]
//还可以利用下标来一次改变一系列数据值,即使新数据和原有数据的数量是不一样的。
shoppingList[4...6] = ["abc","bcd"]
//["苹果", "鸡蛋", "土豆", "鸡肉", "abc", "bcd"]
数组的遍历
for item in shoppingList {
print(item)
}
//苹果
//鸡蛋
//土豆
//鸡肉
//abc
//bcd
for (index, value) in shoppingList. enumerated() {
print("Item \(String(index + 1)): \(value)")
}
// Item 1: 苹果
// Item 2: 鸡蛋
// Item 3: 土豆
// Item 4: 鸡肉
// Item 5: abc
// Item 6: bcd
集合(Sets)
集合(Set)用来存储相同类型并且没有确定顺序的值。当集合元素顺序不重要时或者希望确保每个元素只出现一次时可以使用集合而不是数组。(重点:Sets的元素是不重复的)
Sets类型的哈希值(hash)
一种类型的数据为了能够存在Sets中,它的类型必须是可以被哈细化的.哈希值是一种Int类型,两个相等的数据,它的哈希值是一样的,例如a = b , 那么a.hashValue == b.hashValue. Swift的基本类型都是可以哈希化的,没有关联值的枚举成员值(在枚举有讲述)默认也是可哈希化的。
注意:
你可以使用你自定义的类型作为集合的值的类型或者是字典的键的类型,但你需要使你的自定义类型符合 Swift 标准库中的Hashable协议.符合Hashable协议的类型需要提供一个类型为Int的可读属性hashValue。由类型的hashValue属性返回的值不需要在同一程序的不同执行周期或者不同程序之间保持相同。
因为Hashable协议符合Equatable协议,所以遵循该协议的类型也必须提供一个"是否相等"运算符(==)的实现。这个Equatable协议要求任何符合==实现的实例间都是一种相等的关系。也就是说,对于a,b,c三个值来说,==的实现必须满足下面三种情况:
a == a(自反性)
a == b意味着b == a(对称性)
a == b && b == c意味着a == c(传递性)
关于遵循协议的更多信息,请看协议
集合类型语法
Swift 中的Set类型被写为Set<Element>,这里的Element表示Set中允许存储的类型,和数组不同的是,集合没有等价的简化形式.(因为直接等价的被推断成了Arrays
)
创建和构造一个空的集合
var letters = Set<Character>()
//通过构造器,这里的letters变量的类型被推断为Set<Character>。
print("letters的类型是:Set<Character>,包含\(letters.count) 个元素.")
// 打印 "letters的类型是Set<Character>,包含0个元素."
letters.insert("a")
// letters 现在含有1个 Character 类型的值
letters = []
// letters 现在是一个空的 Set, 但是它依然是 Set<Character> 类型
//利用数组来创建Set
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
// favoriteGenres 被构造成含有三个初始值的集合
//上面的写法还可以简化为下面的代码
//var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]
访问和修改一个集合
//你可以通过Set的属性和方法来访问和修改一个Set。
//Set类型和Arrays一样,拥有.count方法来获取它的元素个数
print("favoriteGenres的元素个数是:\(favoriteGenres.count)个")
//输出:favoriteGenres的元素个数是:3个
//使用布尔属性isEmpty作为一个缩写形式去检查count属性是否为0:
if favoriteGenres.isEmpty {
print("As far as music goes, I'm not picky.")
} else {
print("I have particular music preferences.")
}
// 打印 "I have particular music preferences."
//你可以通过调用Set的insert(_:)方法来添加一个新元素:
favoriteGenres.insert("Jazz")
// favoriteGenres 现在包含4个元素
//你可以通过调用Set的remove(_:)方法去删除一个元素,
//如果该值是该Set的一个元素则删除该元素并且返回被删除的元素值,
//否则如果该Set不包含该值,则返回nil。
//另外,Set中的所有元素可以通过它的removeAll()方法删除。
if let removedGenre = favoriteGenres.remove("Rock") {
print("\(removedGenre)? I'm over it.")
} else {
print("I never much cared for that.")
}
// 打印 "Rock? I'm over it."
//使用contains(_:)方法去检查Set中是否包含一个特定的值
if favoriteGenres.contains("Funk") {
print("I get up on the good foot.")
} else {
print("It's too funky in here.")
}
// 打印 "It's too funky in here."
//遍历一个集合
for genre in favoriteGenres {
print("\(genre)")
}
// Classical
// Jazz
// Hip hop
//为了按照特定顺序来遍历一个Set中的值可以使用sorted()方法,它将返回一个有序数组
for genre in favoriteGenres.sorted() {
print("\(genre)")
}
// prints "Classical"
// prints "Hip hop"
// prints "Jazz
集合操作
你可以高效地完成Set的一些基本操作,比如把两个集合组合到一起,判断两个集合共有元素,或者判断两个集合是否全包含,部分包含或者不相交。
setVennDiagram_2x.png
- 使用intersection(_:)方法根据两个集合中都包含的值创建的一个新的集合。
- 使用symmetricDifference(_:)方法根据在一个集合中但不在两个* 集合中的值创建一个新的集合。
- 使用union(_:)方法根据两个集合的值创建一个新的集合。
- 使用subtracting(_:)方法根据不在该集合中的值创建一个新的集合。
let oddDigits: Set = [1, 3, 5, 7, 9]
let evenDigits: Set = [0, 2, 4, 6, 8]
let singleDigitPrimeNumbers: Set = [2, 3, 5, 7]
oddDigits.union(evenDigits).sorted()
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
oddDigits. intersection(evenDigits).sorted()
// []
oddDigits.subtracting(singleDigitPrimeNumbers).sorted()
// [1, 9]
oddDigits. symmetricDifference(singleDigitPrimeNumbers).sorted()
// [1, 2, 9]
集合成员关系和相等
setEulerDiagram_2x.png- 使用“是否相等”运算符(==)来判断两个集合是否包含全部相同的值。
- 使用isSubset(of:)方法来判断一个集合中的值是否也被包含在另外一个集合中。
- 使用isSuperset(of:)方法来判断一个集合中包含另一个集合中所有的值。
- 使用isStrictSubset(of:)或者isStrictSuperset(of:)方法来判断一个集合是否是另外一个集合的子集合或者父集合并且两个集合并不相等。
- 使用isDisjoint(with:)方法来判断两个集合是否不含有相同的值(是否没有交集)。
let houseAnimals: Set = ["🐶", "🐱"]
let farmAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"]
let cityAnimals: Set = ["🐦", "🐭"]
houseAnimals.isSubset(of: farmAnimals)
// true
farmAnimals.isSuperset(of: houseAnimals)
// true
houseAnimals.isSuperset(of: armAnimals)
//true
farmAnimals.isStrictSuperset(of: houseAnimals)
// true
farmAnimals.isDisjoint(with: cityAnimals)
// true
字典
Swift 的字典使用Dictionary<Key, Value>定义,其中Key是字典中键的数据类型,Value是字典中对应于这些键所存储值的数据类型。
一个字典的Key类型必须遵循Hashable协议,就像Set的值类型。在同一个字典中,一个key不可以出现两次,但是value可以重复出现
也可以用[Key: Value]这样简化的形式去创建一个字典类型。虽然这两种形式功能上相同,但是后者是首选
//创建一个空字典
var namesOfIntegers = [Int: String]()
// namesOfIntegers 是一个空的 [Int: String] 字典,它的键是Int型,值是String型。
//我们可以使用空字典字面量来创建一个空字典,记作[:]
namesOfIntegers[16] = "sixteen"
// namesOfIntegers 现在包含一个键值对
namesOfIntegers = [:]
// namesOfIntegers 又成为了一个 [Int: String] 类型的空字典
//用字典字面量创建字典
//下面的例子创建了一个存储国际机场名称的字典。在这个字典中键是三个字母的国际航空运输相关代码,值是机场名称:
var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
//airports字典被声明为一种[String: String]类型,这意味着这个字典的键和值都是String类型。
//airports字典使用字典字面量初始化,包含两个键值对。
//第一对的键是YYZ,值是Toronto Pearson。第二对的键是DUB,值是Dublin。
访问和修改字典
var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
print(" airports contains \(airports.count) items.")
//airports contains 2 items.
//使用布尔属性isEmpty作为一个缩写形式去检查count属性是否为0:
let emptyOrNot = airports.isEmpty
//emptyOrNot 为否
//使用下标语法来添加新的数据项
airports["LHR"] = "London"
// airports 字典现在有三个数据项
//使用下标语法来改变特定键对应的值:
airports["LHR"] = "London Heathrow"
// "LHR"对应的值 被改为 "London Heathrow
//还可以用字典的方法updateValue(_:forKey:)方法可以设置或者更新特定键对应的值。
//updateValue(_:forKey:) 的功能和上面的一样
//不同的是:updateValue(_:forKey:)这个方法返回更新值之前的原value。
//这样使得我们可以检查更新是否成功。
guard let str = airports.updateValue("香港", forKey: "GZ") else {
print("str is empty")
return
}
//此时:airports 等于:["YYZ": "Toronto Pearson", "DUB": "Dublin", "LHR": "London", "GZ": "广州"]
//也可以使用下标语法来在字典中检索特定键对应的值,
//因为key对应的value可能为nil ,
//所以下标访问方法返回的是对应值的可选类型
if let airportName = airports["GZ"] {
print(airportName)
} else {
print("没有对应的机场")
}
// 打印:广州
//把指定key 对应的 value 设置为 nil, 则这对键值对会被从字典移除
airports["GZ"] = nil
print(airports)
//["YYZ": "Toronto Pearson", "DUB": "Dublin", "LHR": "London"]
//此外,removeValue(forKey:)方法也可以用来在字典中移除键值对。
//这个方法在键值对存在的情况下会移除该键值对并且返回被移除的值或者在没有值的情况下返回nil
if let removedValue = airports. removeValue(forKey: "DUB") {
print("removedValue")
} else {
print("没有对应的机场")
}
//输出: Dublin
字典遍历
//for-in循环来遍历某个字典中的键值对
var person = ["老王":38,"老李":28,"小李":18]
for (name, age) in person {
print("\(name): \(age)")
}
//老李: 28
//小李: 18
//老王: 38
//通过访问keys访问遍历values
for age in person.keys {
print(age)
}
//小李
//老李
//牛爱花
//老王
//通过values 访问keys
for key in person.values{
print(key)
}
//18
//28
//28
//38
//如果我们只是需要使用某个字典的键集合或者值集合
//可以直接使用keys或者values属性构造一个新数组:
let names = [String](person.keys)
print(names) //["小李", "老李", "牛爱花", "老王"]
let ages = [Int](person.values)
print(ages)//[18, 28, 28, 38]
网友评论