您的位置:首页 > 移动开发 > Swift

6.Swift教程翻译系列——Swift集合类型

2015-12-26 10:24 585 查看
英文版PDF下载地址http://download.csdn.net/detail/tsingheng/7480427

Swift提供数组和字典两种集合类型。用来存储很多值的情况。数组有序的存储一组同样类型的值。字典也存储一组同样类型的值可是是无序的。字典中存储的值能够通过一个唯一的标识(也就是Key)来查找。

在Swift中,数组和字典总是清楚自己能存储的值的类型和key的类型。也就是说你不会错误的把其它不正确应的类型存进数组或者字典。所以你也能确定从数组或者字典中取出来的值的类型肯定也不会错了。Swift使用显式类型集合来保证你的代码总是能清除的知道数组和字典中存储的值的类型,确保你在开发阶段就能发现全部类型错误。

NOTE 当你将数组赋值给其它变量或者常量,或者传递给函数或方法的时候。数组的行为跟其它类型是不太一样的。很多其它信息在可变集合与集合类型赋值与拷贝里面介绍。

1.数组

数组能够以有序状态存储同一类型的多个值。同一个值也能够在同一个数组的不同位置多次出现。

Swift数组能存储的值的类型是特定的。他跟OC的NSArray或者NSMutableArray类不一样,这两个类能够存储不论什么对象,不用说明他们返回的值是什么类型。

可是在Swift里,特定的数组能存储的值的类型必需要说明清楚,要么是通过类型标注,要么通过类型判断。并且不需要一定是class类型。假设你创建一个Int值的数组。你就不能向这个数组里面存储除了Int类型意外的不论什么值。Swift数组总是类型安全的,总是清除数组能够存储什么类型。

数组类型简写

Swift数组的类型完整形式是Array<SomeType>这种。SomeType就是数组同意存储的类型。你也能够使用简写形式SomeType[]。尽管说两种形式功能是同样的。可是更推荐使用简写形式,这本手冊也将採取简写形式。

数组字面值

你能够使用数组字面值来初始化数组。这是将一个或多个值定义成数组的简写方式。

数组字面值形式是一组值以逗号分隔,外面再加上中括号。比方[value 1, value 2, value 3]。

以下样例创建了一个数组shoppingList来存数字符串

var shoppingList: String[] = ["Eggs", "Milk"]
// shoppingList has been initialized with two initial items
变量shoppingList被声明为“字符串值的数组”。写作String[]。由于这个数组被声明是字符串类型。所以这个数组就仅仅能存储字符串。这里shoppingList数组被使用两个字符串值的数组字面值来初始化。

NOTE 注意上面数组shoppingList是被声明为变量而不是常量。由于后面样例中还要向这个数组中加入很多其它地元素。

在这个样例中数组字面值仅仅包括了两个字符串,正好匹配shoppingList的声明(仅仅能存储字符串类型的数组),所以使用字面值赋值被同意用来初始化数组shoppingList。

由于Swift有类型判断机制。所以当你使用仅仅包括一种类型的数组字面值来初始化数组的时候是能够不用指明数组类型的。上面shoppingList的声明能够这条语句取代 var shoppingList = ["Eggs", "Milk"] 由于用来初始化的数组字面值包括的类型都是同样的,所以Swift能够判断出Sring[]就是用来声明shoppingList的正确类型。

获取和改动数组

你能够通过数组的方法或者属性或者使用下标语法来获取和改动数组。

要想知道数组拥有几个元素。能够通过数组的仅仅读属性count

println("The shopping list contains \(shoppingList.count) items.")
// prints "The shopping list contains 2 items.
使用属性isEmpty能够作推断count属性是否为0

if shoppingList.isEmpty {
println("The shopping list is empty.")
} else {
println("The shopping list is not empty.")
}
// prints "The shopping list is not empty."
你能够通过调用append方法来向数组的末尾加入元素

shoppingList.append("Flour")
// shoppingList now contains 3 items, and someone is making pancakes
或者也能够使用+=操作符来向数组末尾加入元素:

shoppingList += "Baking Powder"
// shoppingList now contains 4 items
你还能够使用+=符号来向数组中加入一个类型匹配的数组:

shoppingList += ["Chocolate Spread", "Cheese", "Butter"]
// shoppingList now contains 7 items
假设要获取数组中的值就用下标语法,在数组名后面加上中括号。中括号中面写你想要获取的值的序号:

var firstItem = shoppingList[0]
// firstItem is equal to "Eggs”
注意数组中第一个元素的下标是0而不是1。

Swift中的数组下标都是从0開始的。

你能够使用下标语法来改动已经存在数组中的值:

shoppingList[0] = "Six eggs"
// the first item in the list is now equal to "Six eggs" rather than "Eggs”
你还能够使用下标语法一次性改动多个值,即使要替换的数组长度跟使用的下标范围长度不一样都行。以下样例把"chocolate Spread",”Cheese“,”Butter“替换成"Bananas"和"Apples":

shoppingList[4...6] = ["Bananas", "Apples"]
// shoppingList now contains 6 items
NOTE 不能够使用下标语法来向数组末尾加入元素。假设你使用下标语法的时候使用了超出数组现有下标范围的数值,将会发生执行时错误。只是你能够在使用下标的时候先通过比較该下标是否不大于数组的count属性来检測是否越界。除了count是0得情况,数组能够使用的最大下标总是count-1。

假设要再数组特定位置插入元素,须要调用数组的方法insert(atIndex:):

shoppingList.insert("Maple Syrup", atIndex: 0)
// shoppingList now contains 7 items
// "Maple Syrup" is now the first item in the list”
上面样例调用以后将会在数组的最前面也就是下标为0增加元素"Maple Syrup"。

类似的。你能够使用removeAtIndex方法来移除数组中的元素。这种方法移除指定的元素,而且返回被移除的元素(尽管你能够忽略这个返回的元素,可是他还是会返回):

let mapleSyrup = shoppingList.removeAtIndex(0)
// the item that was at index 0 has just been removed
// shoppingList now contains 6 items, and no Maple Syrup
// the mapleSyrup constant is now equal to the removed "Maple Syrup" string”
数组中不论什么元素被移除后空隙都会被填充,所以上面样例移除第0个以后,第0个立即就会被"Six eggs"替换:

firstItem = shoppingList[0]
// firstItem is now equal to "Six eggs”
假设你像移除数组中最后一个元素,使用removeLast方法而不是removeAtIndex方法。这样能够不用再使用count属性。和removeAtIndex方法一样,removeLast也返回被移除的元素:

let apples = shoppingList.removeLast()
// the last item in the array has just been removed
// shoppingList now contains 5 items, and no cheese
// the apples constant is now equal to the removed "Apples" string”
遍历数组

你能够是用for-in循环来遍历数组中的元素

for item in shoppingList {
println(item)
}
// Six eggs
// Milk
// Flour
// Baking Powder
// Bananas
假设你又想获取元素的值又想获取元素的下标,那就使用全局函数enumerate来遍历数组。enumerate函数为每个元素返回一个包括了下标和元素值的元组。你能够解析元素赋值给暂时常亮或者变量作为遍历的一部分:

for (index, value) in enumerate(shoppingList) {
println("Item \(index + 1): \(value)")
}
// Item 1: Six eggs
// Item 2: Milk
// Item 3: Flour
// Item 4: Baking Powder
// Item 5: Bananas
创建和初始化数组

你能够使用初始化语法来创建特定类型的空数组(不设置不论什么初始值)。

var someInts = Int[]()
println("someInts is of type Int[] with \(someInts.count) items.")
// prints "someInts is of type Int[] with 0 items.”
注意数组someInts的类型被是Int[],由于他被设置为Int[]初始化的结果。

或者假设上下文中已经说明了类型信息,比方函数參数或者一个已经定义过类型的变量或常量,那你就能够使用空得数组字面量[]还创建空数组。

someInts.append(3)
// someInts now contains 1 value of type Int
someInts = []
// someInts is now an empty array, but is still of type Int[]
Swfit的数组类型还提供一个初始化器来创建特定长度,各个元素都被指定为默认值的数组。

你须要传递给初始化器须要加入的元素数量和一个初始值:

var threeDoubles = Double[](count: 3, repeatedValue: 0.0)
// threeDoubles is of type Double[], and equals [0.0, 0.0, 0.0]
由于有类型判断。所以在使用这个初始化器的时候是不须要指定数组类型的。由于数组类型从默认值能够判断出来:

var anotherThreeDoubles = Array(count: 3, repeatedValue: 2.5)
// anotherThreeDoubles is inferred as Double[], and equals [2.5, 2.5, 2.5]
最后。你能够通过两个现有的类型匹配的数组相加来创建新的数组。新数组的类型将从相加的两个数组中判断出来:

var sixDoubles = threeDoubles + anotherThreeDoubles
// sixDoubles is inferred as Double[], and equals [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]


2.字典
字典是一个能够存储同一类型的多个值的容器。各个值跟一个唯一的key关联。key在字典中是值的唯一标识。

跟数组中的元素不同的是,字典中的元素没有特定的顺序。当你须要使用元素的标识来查找的时候能够使用字典,在现实世界中我们使用字典依据单词来查找定义。

Swift字典也是明白知道自己能够存储的key可value的类型。字典和OC的NSDictionary以及NSMutableDictionary不同,NSDictionary和NSMutableDictionary能够使用不论什么对象作为key和value。并且不须要提供这些对象的不论什么类型信息。在Swift中。一个特定的字典能够存储的key和value的类型总是要指明的,要么通过类型标注,要么通过类型判断。

Swift的字典类型写作Dictionary<KeyType, ValueType>。KeyType是能够用作字典Key的类型。ValueType是字典能够存储的value的类型。

唯一的限制是KeyType必须是hashable,也就是说他必需要提供一个另自己唯一表示的方式。Swift的全部基础类型(比方String,Int,Double和Bool)默认都是hashable。所以这些类型都能够作为字典的key。

没有关联值的枚举成员默认也是hashable

字典字面值

你能够使用字典字面值来初始化字典。字典字面值跟前面的数组字面值语法类似。字典字面值是将一个或多个key-value对写成字典集合的简便方式。

一个key-value对是一个key与一个value的绑定。

在字典字面值中,各个key-value用逗号隔开并被中括号包围,key与value用冒号隔开:

[key 1: value 1, key 2: value 2, key 3: value 3]

以下样例创建了一个字典来存储国际机场的名称:

var airports: Dictionary<String, String> = ["TYO": "Tokyo", "DUB": "Dublin"]

字典airport被声明为Dictionary<String, String>类型。意思是”key类型为String,value类型也为String的字典“

NOTE 字典airports被声明为变量而不是常量,由于后面样例中还会向当中加入很多其它元素。

字典airports被使用包括两个key-value对的字典字面值初始化。

第一对key是”TYO",value是”Tokyo“。第二对key是"DUB"。value是”Dublin“。

这个字典字面值包括两个字符串:字符串对。正好匹配变量airports声明的类型,所以使用字典字面值赋值被同意用来初始化字典airports。

也数组一样,假设你使用key和value保持一致的字典字面值来初始化字典的时候也不必要再写出字典的类型。airports的初始化能够使用以下的简写方式:

var airports = ["TYO": "Tokyo", "DUB": "Dublin"]

由于字典字面值中各个元素的key类型是一样的,各个元素的value类型也是一样的,所以swift能够判断出来Dictionary<String, String>就是用来初始化字典airport的正确类型。

获取和改动字典

你能够通过字典的属性或者方法或者下标语法来获取和改动字典。和数组一样,你能够使用count属性来查看字典中的元素个数。

println("The dictionary of airports contains \(airports.count) items.")
// prints "The dictionary of airports contains 2 items.
你能够使用下标语法想字典中加入新元素。使用新的Key作为下标值,而且使用心得value来赋值:

airports["LHR"] = "London"
// the airports dictionary now contains 3 items
你也能够使用下标语法来改动特定Key关联的值:

airports["LHR"] = "London Heathrow"
// the value for "LHR" has been changed to "London Heathrow
还能够使用字典的updateValue(forKey:)方法来设置或者更新特定key相应的值。想上面的下标样例一样。假设相应的value不存在,就加入一条记录,假设存在就更新记录。只是和下标语法不一样的是,updateValue(forKey:)方法返回的是旧的值。这样你能够检查更新有没有生效。

updateValue(forKey:)方法返回字典value类型的可选值。比方上面存储字符串值的字典,该方法返回字符串可选值。假设更新前value存在,返回的可选值其中存储原来的value,假设不存在,返回的就是nil。

if let oldValue = airports.updateValue("Dublin International", forKey: "DUB") {
println("The old value for DUB was \(oldValue).")
}
// prints "The old value for DUB was Dublin.”
你也能够使用下标语法来查询子字典中特定key相应的值。由于同意使用不存在的key。所以使用字典下标返回的时一个可选值。

假设字典包括key所相应的value,返回的就是这个value,假设不包括。返回的就是nil。

if let airportName = airports["DUB"] {
println("The name of the airport is \(airportName).")
} else {
println("That airport is not in the airports dictionary.")
}
// prints "The name of the airport is Dublin International.”
你能够使用下标语法给特定key的值赋值为nil来从字典中删除这个元素。

airports["APL"] = "Apple International"
// "Apple International" is not the real airport for APL, so delete it
airports["APL"] = nil
// APL has now been removed from the dictionary
或者还能够使用removeValueForKey方法来移除元素。

假设存在元素,就移除然后返回该元素。假设不存在就直接返回nil。

if let removedValue = airports.removeValueForKey("DUB") {
println("The removed airport's name is \(removedValue).")
} else {
println("The airports dictionary does not contain a value for DUB.")
}
// prints "The removed airport's name is Dublin International.”
遍历字典

你能够使用for-in循环来遍历字典。字典哥哥元素返回一个(key, value)的元组,你能够解析元组成员到暂时变量或者常量中:

for (airportCode, airportName) in airports {
println("\(airportCode): \(airportName)")
}
// TYO: Tokyo
// LHR: London Heathrow
你还能够通过字典的额keys属性和values属性来获取字典的key集合或者value集合:

for airportCode in airports.keys {
println("Airport code: \(airportCode)")
}
// Airport code: TYO
// Airport code: LHR

for airportName in airports.values {
println("Airport name: \(airportName)")
}
// Airport name: Tokyo
// Airport name: London Heathrow
假设你须要通过一个数组实例来使用字典的keys或者values,就用属性keys或者values来初始化数组:

let airportCodes = Array(airports.keys)
// airportCodes is ["TYO", "LHR"]

let airportNames = Array(airports.values)
// airportNames is ["Tokyo", "London Heathrow"]
NOTE Swift的字典是无序集合。当遍历字典的时候。字典中keys,values以及key-value对的获取顺序都是不固定的。

创建空字典

和数组一样,你能够使用初始化语法来创建特定类型的空字典:

var namesOfIntegers = Dictionary<Int, String>()
// namesOfIntegers is an empty Dictionary<Int, String>
这个样例创建了Int,String类型的字典来保存整数的名称。key的类型是Int。value的类型是String。

假设上下文已经提供了类型信息。就能够直接使用空字典字面值来创建空字典,空字典字面值写作[:]:

namesOfIntegers[16] = "sixteen"
// namesOfIntegers now contains 1 key-value pair
namesOfIntegers = [:]
// namesOfIntegers is once again an empty dictionary of type Int, String
NOTE Swift的数组和字典类型是泛型集合的实现。很多其它泛型和集合信息请查阅泛型。

3.可改动集合

数组和字典将多个元素存储到一个集合中。假设你创建了一个数组或者字典,而且赋值给一个变量,那么创建的集合就是能够改动的。也就是说你能够在集合创建以后加入很多其它地元素或者移除已有元素来改变集合的长度。反过来假设你把数组或者字典赋值给常量。那么这个数组或者字典就是不可变得。长度也不能改变。

对于字典来说,不可变星还以为这你不恩给你替换已有的key相应的value。不可变的字典内容一旦被设置就不能再改变。

对于数组来说不可变性有一点点不同。

你还是不能做一些可能改变数组唱的的操作,可是你能够替换数组中已有的值。这样能够让Swift的数组在固定长度的时候提供更好地性能。

NOTE 当集合长度不须要改变的时候尽量要创建不可变的集合。

这样Swift编译器能够优化你创建的集合的性能。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: