Swift 初学者 ( 11/12 ) 字典

简介

这是一个Swift语言教程,基于最新的iOS 9,Xcode 7.3和Swift 2.2,会为你介绍Swift编程非常基础的内容。从电脑如何工作的全程基本原理到语言结构,你会足够了解这门语言,来处理数据和管理代码的行为。

Swift 初学者 ( 11/12 ) 字典_第1张图片

快速链接

  • 一个下午让你掌握Swift基础 ( 1/9 ) 编程本质 & Playground基础
  • 一个下午让你掌握Swift基础 ( 2/9 ) 变量 & 常量
  • 一个下午让你掌握Swift基础 ( 3/9 ) 数字类型 & 操作
  • 一个下午让你掌握Swift基础 ( 4/9 ) 字符串
  • 一个下午让你掌握Swift基础 ( 5/9 ) 做判断
  • 一个下午让你掌握Swift基础 ( 6/9 ) 重复步骤
  • 一个下午让你掌握Swift基础 ( 7/9 ) 函数
  • 一个下午让你掌握Swift基础 ( 8/9 ) 闭包
  • 一个下午让你掌握Swift基础 ( 9/9 ) 可选值
  • Swift 初学者 ( 10/12 ) 数组
  • Swift 初学者 ( 12/12 ) 集合

字典

字典(dictionary)是没有顺序的一对一对的集合,每一对由一个键(key)和一个值(value)组成。

Swift 初学者 ( 11/12 ) 字典_第2张图片

在上面的示意图可以看到,键是唯一的。相同的键不能在一个字典里出现两次,但不同的键可以指向相同的值。所有的键都要是相同的类型,所有的值也要是相同的类型。

当你想通过一个标识符查找值时,字典很有用。例如,这篇教程内容的表格映射了章节名到他们的链接,让你轻松地就可以快速跳到想阅读的章节。

这和数组有什么不同?用数组,你只能通过它的索引获取一个值,必须要是整数,并且所有索引都要是按顺序的。在一个字典里,键可以是任意类型,也不需要有特定的顺序。

创建字典

当你在创建字典的时候,你可以显示声明键的类型和值的类型。这是字典显示声明的例子:

let pairs: Dictionary

这和数组的显示声明相似,但这里的尖括号里有两个类型,用逗号间隔:键的类型和值的类型。这个例子里,paris 是一个不可以被修改的字典,字符串作为键,整数作为值。

隐式声明

Swift 也能从初始化的类型中推断出字典的类型:

let inferredPairs = Dictionary()

或者用更推荐的简写:

let alsoInferredPairs = [String: Int]()

在方括号里,键的类型后面跟着一个冒号,然后是值的类型。这是声明字典最常用的方式,你会在本教程里全程使用它。

字典字面值

如果你想用初始值声明一个字典,你可以使用字典字面值。这是用逗号间隔的键值对列表,包裹在方括号里。

对于上一篇教程里你的纸牌游戏,不需要使用两个数组来映射选手到他们的分数,用字典字面值就好了:

let namesAndScores = ["Anna": 2, "Brian": 2, "Craig": 8, "Donna": 6]
print(namesAndScores)
// > ["Brian": 2, "Anna": 2, "Craig": 8, "Donna": 6]

这个例子里,字典有一对对 [String: Int]。当你打印字典的时候,可以看到这几对并没有特殊的顺序。

空的字典字面值看起来像这样:[:]。你可以像这样使用它来把一个已经存在的字典清空:

var emptyDictionary: [Int: Int]
emptyDictionary = [:]

访问值

就像数组一样,有几种方式来访问字典的值。

使用下标

字典支持下标来访问值。不像数组,不是用索引来访问值,而是用它的键。例如你希望得到 Anna 的分数,就这样输入:

print(namesAndScores["Anna"])
// > Optional(2)

注意返回值是可选值。字典会检查有没有哪一对的键是“Anna”,如果有,返回它的值。如果字典没有找到键,返回 nil。

print(namesAndScores["Greg"])
// > nil

还记得数组如果下标越界访问就会导致一个运行时错误吗,但字典不同,因为他们的结果被包装为可选值。

你现在可能还没有理解,但可选值的下标访问真的强大。它允许你找一个特定选手是否在游戏里,而不需要遍历所有的键,但使用数组的话就必须要这么做了。

使用 properties 和方法

字典有相同的 isEmpty 和 count properties,和数组一样:

print(namesAndScores.isEmpty)
// > false
print(namesAndScores.count)
// > 4

如果你只想看字典的键或值,你可以从字典的 keys 或 values properties 创建一个数组,各自的:

print(Array(namesAndScores.keys))
// > ["Brian", "Anna", "Craig", "Donna"]
print(Array(namesAndScores.values))
// > [2, 2, 8, 6]

这些就是你在前一篇文章里学的常规数组。

修改字典

添加对

Bob 想加入游戏。

Swift 初学者 ( 11/12 ) 字典_第3张图片

让他加入之前看看他的信息:

var bobData = ["name": "Bob", "profession": "Card Player", "country": "USA"]

这个字典是 [String: String] 类型的,它可以被修改因为被分配到变量了。假设你获得了更多关于 Bob 的信息,想把它加到字典里。这么做:

bobData.updateValue("CA", forKey: "state")

甚至还有一个更短的方式,使用下标:

bobData["city"] = "San Francisco"

Bob 是一个职业纸牌选手。到目前为止,他听起来很适合填入你的名单。

迷你练习

写一个函数,打印给定选手的城市和国家。

更新值

又出现了之前的情况,Bob 曾经在玩牌的时候被逮到作弊。他不只是专业的,还是出老千的!他让你改掉他的名字和职业,这样就没人会认出他了。

看起来 Bob 热切的希望浪子回头,你同意了。首先,你把他的名字从 Bob 改为了 Bobby:

bobData.updateValue("Bobby", forKey: "name")
// > Bob

你读添加对的时候就已经看过这个方法了。为什么它返回字符串“Bob”?updateValue(_:forKey:) 用新的值替换了给定键的值,然后返回老的值。如果键不存在,这个方法会添加新的一对,然后返回 nil。

就像添加一样,你可以用更少的代码来完成,使用下标:

bobData["profession"] = "Mailman"

就像第一个方法,代码更新了这个键的值,或者如果键不存在,创建新的一对。

移除对

Bob-额,抱歉-Bobby,还是觉得不够安全,他希望你移除所有有关他来自哪里的信息:

bobData.removeValueForKey("state")

这个方法会移除“state”键以及它在字典中的关联值。就像你可能预料到的,使用下标是更简短的方式:

bobData["city"] = nil

分配 nil 为一个键的关联值会从字典中移除这一对。

遍历字典

当你想遍历字典的时候,for-in 循环也是有效的。但因为字典里的项目都是成对的,你需要用元组:

for (key, value) in namesAndScores {
    print("\(key) - \(value)")
}
// > Brian - 2
// > Anna - 2
// > Craig - 8
// > Donna - 6

只遍历键也是可以的:

for key in namesAndScores.keys {
  print("\(key), ", terminator: "") // no newline
}
print("") // print one final newline
// > Brian, Anna, Craig, Donna,

你可以用同样的方式只遍历值,通过字典的 values property。

序列操作

你也可以对字典做序列操作。例如,你可以用 reduce(_:combine:) 来替换前一个代码片段为只一行代码:

let namesString = namesAndScores.reduce("", combine: { $0 + "\($1.0), " })
print(namesString)

在一个 reduce 语句里,$0 是指部分合并的结果,$1 指向当前元素。因为字典的元素是元祖,你需要使用 $1.0 来获得这一对的

让我们看看如何用 filter(_:) 来找到所有分数不足 5 的选手:

print(namesAndScores.filter({ $0.1 < 5 }))
// > [("Brian", 2), ("Anna", 2)]

这里用 $0.1 来访问这一对的

字典操作的运行时间

为了能够检测字典是如何运作的,需要理解哈希(hashing)是什么,以及它是如何工作的。哈希是转换值 - String, Int, Double, Bool, 等等 - 到数字化的值的过程,叫做哈希值

Swift 里,所有基本类型都是可以被哈希的,并且有一个 hashValue property。这是例子:

print("some string".hashValue)
// > 4799450059642629719
print(1.hashValue)
// > 1
print(false.hashValue)
// > 0

哈希值必须是确定性的 - 意味着给定一个值必须总是返回同样的哈希值。不论你计算“some string”的哈希值,总是会得到相同的值。

字典只能存储可以被哈希的键。这是一个超出本教程范围的细节实现了,但处理哈希让检查独一性和搜索更轻松了。

这是多种字典操作表现的消耗:

分配元素:获得指定键的值是一个常量时间操作,即O(1)。
加入元素:要插入一个元素,字典需要计算这个键的哈希值,然后基于那个哈希来存储数据。这些都是 O(1) 操作。
删除元素:再一次,字典需要计算哈希值来确切了解在哪里可以找到元素,然后移除它。这也是一个 O(1) 操作。
搜索元素:像上面提到的,访问元素有一个常量运行时间,所以搜索的复杂度也是 O(1)。

关键点

  • 字典是没有顺序的键值对集合。
  • 字典的都是相同类型的,值也是相同类型的。
  • 使用 下标 来获得值,以及添加、更新或移除对。
  • 遍历字典会返回元祖,同时包含键和值。

接下来去哪儿?

字典和数组相当不同:他们没有顺序,有键和值,以及有杰出的搜索表现。
但是,接口在下标和 for-in 循环上很相似。你会在后面学习到,“协议”,这个相似性要感谢跨越集合类型通用的接口。
在下一篇,你会学习集合(sets),结合了你已经从字典和数组里学到的概念。

挑战

挑战 A:你就是编译器

下列哪个是有效语句?

1. let dict1 = Int, Int()
2. let dict2 = []
3. let dict3 = [Int: Int]()

对于接下来四个语句,使用下面的字典:

let dict4 = ["One": 1, "Two": 2, "Three": 3]

4. dict4[1]
5. dict4["One"]
6. dict4["Zero"] = 0
7. dict4[0] = "Zero"

对于接下来的三个语句,使用下面的字典:

var dict5 = ["NY": "New York", "CA": "California"]

8. dict5["NY"]
9. dict5["WA"] = "Washington"
10. dict5["CA"] = nil

挑战 B:替换字典值

写一个函数,交换字典里两个键的值。这是函数结构:

func swapValueForKey(key1: String, withValueForKey key2: String, inDictionary: [String: Int]) -> [String: Int]

挑战 C:搜索字典

给定一个字典,以两个字母的州代号为键,并以完整的州名为值,写一个函数输出所有名字不超过八个字符的州。例如,对于字典 ["NY": "New York", "CA":"California"],输出应该是 “California”。

挑战 D:组合字典

写一个函数,把两个字典组合为一个。如果一个特定的键在两个字典都出现了,忽略第一个字典的对。这是函数结构:

func combine(dict1: [String: String], with dict2: [String: String]) ->[String: String]

挑战源代码

https://yunpan.cn/cMwZ6jA956jsC (提取码:0df7)


介绍

欢迎来到Swift世界!Swift是一门苹果在2014年夏天发布的编程语言。从那之后,Swift发布了一个主要的版本跳跃,成为了开始在苹果平台:iOS,OS X,watchOS和tvOS开发的最简单的方式。

谁适合这篇教程

这篇教程适合懂一点编程、并且希望学习Swift的人。也许你已经为网站写过一些JavaScript代码,或者用Python写过一些简短的程序。这篇教程就是为你准备的!你会学习到编程的基本概念,同时也会成为Swift语言小能手。

如果你是赤裸裸的编程新手,这篇教程也是为你准备的!教程里贯穿有简短的锻炼和挑战来给你一些编程练习,同时测试你的知识。

需要准备什么

要看这篇教程,你需要准备如下的东西:

  • 一台运行OS X El Captian(10.11)的Mac,带有最新发布的更新并且安装了安全补丁。这样你才能够安装需要的开发工具:最新版本的Xcode。
  • Xcode 7.3 或更新的版本。Xcode是用Swift写代码的主要开发工具。最小也需要Xcode 7.3版本,因为那个版本包含Swift 2.2。你可以免费从Mac App Store下载Xcode的最新版本,这里:http://apple.co/1FLn51R。

如果你还没有安装Xcode最新版本,在继续看下面的教程前要确定安装。

如何使用这篇教程

每篇教程都会介绍触手可及的话题理论,伴随大量Swift代码来示范在学习的实际的应用程序。

教程里的所有代码都是平台中立的;这意味着不是为iOS、OS X或任何其它平台而特定。代码在playgrounds里运行,你在本篇中已经学习了。

在剩下的教程里,你可以把代码在自己的playground里输入进去。这样你就可以和代码“玩耍”(play around),做一些改变立即就能看见代码运行的结果。

剩下的教程里会贯穿实际小练习,都是简短的练习,关于触手可及的主题。每篇的末尾也有挑战,会有编程问题也会有长一点的代码练习来测试你的知识。做完就能掌握大部分的Swift基础知识。

你可能感兴趣的:(Swift 初学者 ( 11/12 ) 字典)