[翻译]Swift编程语言——集合类型

集合类型

Swift提供了三种集合类型,数组、set和字典,用来存放一系列内容。数组顺序存放统一类型的值。set是互不相同值的无序集合。字典也是键值对的无序集合。

Swift中数组、set和字典的键和值的类型是明确的。这就意味着你不能将一个不符合的类型值塞入到集合类型中。也意味着从集合中取到的类型一定是确定的。

Note

Swift的数组、set和字典是作为泛型集合的实现的。更多的关于泛型类型和集合的内容,参见 泛型 一章。

集合的易变性

如果你创建了一个集合,并且将其赋值给了一个变量,这个集合就具有了易变性。意思就是在这个集合被创建后,它可以被添加内容、移除内容、或者改变内容。相反,如果你将这个集合赋值给了一个常量,它就不能被修改了,他的长度和内容都不能被修改。
不能被修改的集合最好声明为常量,这样Swfit编译器会对其优化处理。

数组

数组可以接受多个同一类型的值,同一值可以出现在多个不同的位置。
Swfit的数组和OC中的不同点在于其可以存放的值类型,OC中的NSArray 和NSMutableArray 能够接受任何类型的值而且在访问其中内容时没有任何有关类型的提示。Swift的数组存放类型是明确的,类型声明可以是一个明确的类型或者接口或者特定类。如果你创建了一个Int类型的数组,你就不能向其添加任何非Int的数据。Swift的数组是类型安全的,你能明确的知道其中存放的内容类型。

数组类型的简短语法

完整版:Array 或者简化版:[SomeType]。尽管二者功能效果一样,但简化版本是首选,本文将在涉及这方面的情形都采用简化版本。

数组字面值

你可以在用array声明一个数组后,给它赋值,赋值的格式如下:
[value 1,value 2,value 3]
下面的例子创建了一个叫shoppingList 的数组,里面存储字符串:
​var​ ​shoppingList​: [​String​] = [​”Eggs”​,​”Milk”​]
​// shoppingList has been initialized with two initial items
这个例子中字面值包括了两个字符串没有其它类型,和数组的类型声明一致,所以赋值语句被允许进行,两个字符串作为初始化的参数给了初始化方法。
凭借Swift的类型接口,如果你的初始化数据里面是相同的类型,你可以省去数组的类型定义:
​var​ ​shoppingList​ = [​”Eggs”​,​”Milk”​]
因为所有的值都是同一类型,所以Swift可以推断出变量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"

Swift的数组下标从0开始。
你也可以通过下标修改数组内容:

​shoppingList​[​0​] = ​"Six eggs"
​// the first item in the list is now equal to "Six eggs" rather than "Eggs"

你可以使用下标一次替换数组内一定范围的内容,如果你要修改的范围和你提供的修改值个数不符也没有关系。

​shoppingList​[​4​...​6​] = [​"Bananas"​,​"Apples"​]
​// shoppingList now contains 6 items

疑问:用下标的范围表示法?是采用0开始还是1?上例中操作前数组长度为6吧?
你不能通过下标向一个数组照插入内容。通过下标访问和修改内容时,如果下表超出范围,会有一个运行时错误。你可以通过检查数组长度(通过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
将"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

删除操作后,数组中出现了间隙,后续的内容会向前填充。这时的第一个元素已经是:”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 apples
​// 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

具体可以查看循环 for-in语法。

创建和初始化数组(本节已经删除)

你可以创建一个特定类型的空数组:

​var​ ​someInts​ = [​Int​]()
​println​(​"someInts is of type [Int] with ​\(​someInts​.​count​)​ items."​)
​// prints "someInts is of type [Int] with 0 items."

这样写,someInts只接受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]

Swift的数组初始化方法提供了设置数组长度和缺省值的功能。数组长度对应的参数叫:count,缺省值对应的参数叫:repeatedValue

​var​ ​threeDoubles​ = [​Double​](​count​: ​3​,​repeatedValue​: ​0.0​)
​// threeDoubles is of type [Double],and equals [0.0,0.0,0.0]

创建了一个类型为Double,长度为3,缺省值为0.0的数组。

你可以用+将两个数组组合在一起,创建出了一个类型相同的数组:

​var​ ​anotherThreeDoubles​ = [​Double​](​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],2.5]

Sets

一个Set存储相同类型的不同值,而且不排序。可以在不关心排序的情形使用Set替代数组。在需要限制一个元素在集合中只能出现一次时,使用Set。

NOTE
Swift的Set类型是与系统底层NSSet类的桥梁。更多的关于使用Set操控底层和Cocoa的信息,参见 用Swift操控Cocoa和Objective-C。

字典

字典是个存放同一类型内容的容器,在字典中每个内容都有唯一对应的键与其对应。和数组不同,字典中的内容没有特定的顺序而言。和现实中的字典一样,你可以通过键查找字典中的内容。
Swift的字典明确了键和值的类型。这和OC中的NSDictionary 、NSMutableDictionary 不同。

字典类型的简写

Dictionary

字典的字面值

你可以像数组那样给出字典的字面值用于初始化。字面值是若干键-值对构成的。
[key 1: value 1,key 2: value 2,key 3: value 3]
下面这个例子中,字典的键是三个字母构成的航空协会编码,对应的值是机场的名字:
​var​ ​airports​: [​String​: ​String​] = [​”YYZ”​: ​”Toronto Pearson”​,​”DUB”​: ​”Dublin”​]
这个名字为airports的字典是一个[String:String]类型,意思就是一个键是String类型、值是String类型的字典。
这个字典被定义为变量,因为我们后面需要修改它。
和数组类似,省去类型后,简写的方式为:
var​ ​airports​ = [​”YYZ”​: ​”Toronto Pearson”​,​”DUB”​: ​”Dublin”​]
因为赋值的内容 类型都一样,所以Swift编译器可以推断出他们的正确类型。

访问和修改字典

访问和修改字典可以通过它的属性和方法,或者通过下标。和数组一样,count这个只读属性可以告诉你字典的长度。

​println​(​"The airports dictionary contains ​\(​airports​.​count​)​ items."​)
​// prints "The airports dictionary contains 2 items."

isEmpty 属性判断一个字典是否长度是0

​if​ ​airports​.​isEmpty​ {
​ ​println​(​"The airports dictionary is empty."​)
​} ​else​ {
​ ​println​(​"The airports dictionary is not empty."​)
​}
​// prints "The airports dictionary is not empty."

可以采用下标添加一个内容到一个字典,使用一个从未使用的键做下标,然后赋值给它(键值的类型都要对):

airports​[​"LHR"​] = ​"London"
​// the airports dictionary now contains 3 items

也可以通过下标修改字典的一个内容:

​airports​[​"LHR"​] = ​"London Heathrow"
​// the value for "LHR" has been changed to "London Heathrow"

另外的一种方式通过updateValue(forKey:)方法,设置或修改指定键的内容。和下标方式一样,这个方式在没有对应的值的时候创建一个值给对应的键,在有对应值的时候修改那个值。和下标方式不同的地方是,这个方法在修改了值的时候,会返回原来的值。这个功能让你能够检查更新有没有生效。

updateValue(forKey:)返回的是一个字典值类型的可选类型。如果做了修改操作,将返回修改前的值;否则将返回nil;

​if​ ​let​ ​oldValue​ = ​airports​.​updateValue​(​"Dublin Airport"​,​forKey​: ​"DUB"​) {
​ ​println​(​"The old value for DUB was ​\(​oldValue​)​."​)
​}
​// prints "The old value for DUB was Dublin."

同理,用下标访问字典的内容,返回的也是一个字典值类型的可选类型。有值返回值,没有值返回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 Airport."

通过下标方式,用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 Airport."

遍历字典

你可以通过for-in语句遍历一个字典,每个字典有对应有一个由键值对构成的元组,处理这个元组即可。

for​ (​airportCode​,​airportName​) ​in​ ​airports​ {
​ ​println​(​"​\(​airportCode​)​: ​\(​airportName​)​"​)
​}
​// LHR: London Heathrow
​// YYZ: Toronto Pearson

当然你可以通过遍历键或者值的方式遍历整个字典:

​for​ ​airportCode​ ​in​ ​airports​.​keys​ {
​ ​println​(​"Airport code: ​\(​airportCode​)​"​)
​}
​// Airport code: LHR
​// Airport code: YYZ
​
​for​ ​airportName​ ​in​ ​airports​.​values​ {
​ ​println​(​"Airport name: ​\(​airportName​)​"​)
​}
​// Airport name: London Heathrow
​// Airport name: Toronto Pearson

如果你想将字典的键或者值分别存放到数组中,创建两个数组就行了:

let​ ​airportCodes​ = [​String​](​airports​.​keys​)
​// airportCodes is ["LHR","YYZ"]
​
​let​ ​airportNames​ = [​String​](​airports​.​values​)
​// airportNames is ["London Heathrow","Toronto Pearson"]

字典是无序的容器,The order in which keys,values,and key-value pairs are retrieved when iterating over a dictionary is not specified.

创建一个空的字典

var​ ​namesOfIntegers​ = [​Int​: ​String​]()
​// namesOfIntegers is an empty [Int: String] dictionary

如果字典的类型确定了,可以用[:]将字典重新置为空:

​namesOfIntegers​[​16​] = ​"sixteen"
    ​// namesOfIntegers now contains 1 key-value pair
    ​namesOfIntegers​ = [:]
    ​// namesOfIntegers is once again an empty dictionary of type [Int: String]

字典键类型要有哈希值

字典键的类型需要提供比较哈西值的方法。哈西值是一个Int的数字,用来比较两个对象是否相等的。这么说吧,如果两个对象相等,那么他们的哈希值相等。
所有Swfit的基本类型都有默认的哈希值,自然可以作为字典的键。没有关联值(在枚举中有描述)的枚举成员值默认都是hashable的。

NOTE

可以用自定义的类型做字典的键,前提是你的类遵循Swift的标准库中的Hashable 协议。具体做法是需要有个一叫做hashValue的Int类型的可读属性(getter),还要给出“相等”操作符(==)的实现。一个类型的hasValue属性返回值不需要经过相同程序的执行得到一样的结果,同样不需要经过不同的程序执行得到一样的结果。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘贴.待开发的功能:1.支持自动生成约束2.开发设置页面3.做一个浏览器插件,支持不需要下载整个工程,可即时操作当前蓝湖浏览页面4.支持Flutter语言模板生成5.支持更多平台,如Sketch等6.支持用户自定义语言模板
现实生活中,我们听到的声音都是时间连续的,我们称为这种信号叫模拟信号。模拟信号需要进行数字化以后才能在计算机中使用。目前我们在计算机上进行音频播放都需要依赖于音频文件。那么音频文件如何生成的呢?音频文件的生成过程是将声音信息采样、量化和编码产生的数字信号的过程,我们人耳所能听到的声音频率范围为(20Hz~20KHz),因此音频文件格式的最大带宽是20KHZ。根据奈奎斯特的理论,音频文件的采样率一般在40~50KHZ之间。奈奎斯特采样定律,又称香农采样定律。...............
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿遍又亿遍,久久不能离开!看着小仙紫姐姐的蹦迪视频,除了一键三连还能做什么?突发奇想,能不能把舞蹈视频转成代码舞呢?说干就干,今天就手把手教大家如何把跳舞视频转成代码舞,跟着仙女姐姐一起蹦起来~视频来源:【紫颜】见过仙女蹦迪吗 【千盏】一、核心功能设计总体来说,我们需要分为以下几步完成:从B站上把小姐姐的视频下载下来对视频进行截取GIF,把截取的GIF通过ASCII Animator进行ASCII字符转换把转换的字符gif根据每
【Android App】实战项目之仿抖音的短视频分享App(附源码和演示视频 超详细必看)
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至2022年4月底。我已经将这篇博客的内容写为论文,上传至arxiv:https://arxiv.org/pdf/2204.10160.pdf欢迎大家指出我论文中的问题,特别是语法与用词问题在github上,我也上传了完整的项目:https://github.com/Whiffe/Custom-ava-dataset_Custom-Spatio-Temporally-Action-Video-Dataset关于自定义ava数据集,也是后台
因为我既对接过session、cookie,也对接过JWT,今年因为工作需要也对接了gtoken的2个版本,对这方面的理解还算深入。尤其是看到官方文档评论区又小伙伴表示看不懂,所以做了这期视频内容出来:视频在这里:本期内容对应B站的开源视频因为涉及的知识点比较多,视频内容比较长。如果你觉得看视频浪费时间,可以直接阅读源码:goframe v2版本集成gtokengoframe v1版本集成gtokengoframe v2版本集成jwtgoframe v2版本session登录官方调用示例文档jwt和sess
【Android App】实战项目之仿微信的私信和群聊App(附源码和演示视频 超详细必看)
用Android Studio的VideoView组件实现简单的本地视频播放器。本文将讲解如何使用Android视频播放器VideoView组件来播放本地视频和网络视频,实现起来还是比较简单的。VideoView组件的作用与ImageView类似,只是ImageView用于显示图片,VideoView用于播放视频。...
采用MATLAB对正弦信号,语音信号进行生成、采样和内插恢复,利用MATLAB工具箱对混杂噪声的音频信号进行滤波
随着移动互联网、云端存储等技术的快速发展,包含丰富信息的音频数据呈现几何级速率增长。这些海量数据在为人工分析带来困难的同时,也为音频认知、创新学习研究提供了数据基础。在本节中,我们通过构建生成模型来生成音频序列文件,从而进一步加深对序列数据处理问题的了解。
基于yolov5+deepsort+slowfast算法的视频实时行为检测。1. yolov5实现目标检测,确定目标坐标 2. deepsort实现目标跟踪,持续标注目标坐标 3. slowfast实现动作识别,并给出置信率 4. 用框持续框住目标,并将动作类别以及置信度显示在框上
数字电子钟设计本文主要完成数字电子钟的以下功能1、计时功能(24小时)2、秒表功能(一个按键实现开始暂停,另一个按键实现清零功能)3、闹钟功能(设置闹钟以及到时响10秒)4、校时功能5、其他功能(清零、加速、星期、八位数码管显示等)前排提示:前面几篇文章介绍过的内容就不详细介绍了,可以看我专栏的前几篇文章。PS.工程文件放在最后面总体设计本次设计主要是在前一篇文章 数字电子钟基本功能的实现 的基础上改编而成的,主要结构不变,分频器将50MHz分为较低的频率备用;dig_select
1.进入官网下载OBS stdioOpen Broadcaster Software | OBS (obsproject.com)2.下载一个插件,拓展OBS的虚拟摄像头功能链接:OBS 虚拟摄像头插件.zip_免费高速下载|百度网盘-分享无限制 (baidu.com)提取码:6656--来自百度网盘超级会员V1的分享**注意**该插件必须下载但OBS的根目录(应该是自动匹配了的)3.打开OBS,选中虚拟摄像头选择启用在底部添加一段视频录制选择下面,进行录制.
Meta公司在9月29日首次推出一款人工智能系统模型:Make-A-Video,可以从给定的文字提示生成短视频。基于**文本到图像生成技术的最新进展**,该技术旨在实现文本到视频的生成,可以仅用几个单词或几行文本生成异想天开、独一无二的视频,将无限的想象力带入生活
音频信号叠加噪声及滤波一、前言二、信号分析及加噪三、滤波去噪四、总结一、前言之前一直对硬件上的内容比较关注,但是可能是因为硬件方面的东西可能真的是比较杂,而且需要渗透的东西太多了,所以学习进展比较缓慢。因为也很少有单纯的硬件学习研究,总是会伴随着各种理论需要硬件做支撑,所以还是想要慢慢接触理论学习。但是之前总找不到切入点,不知道从哪里开始,就一直拖着。最近稍微接触了一点信号处理,就用这个当作切入点,开始接触理论学习。二、信号分析及加噪信号处理选用了matlab做工具,选了一个最简单的语音信号处理方
腾讯云 TRTC 实时音视频服务体验,从认识 TRTC 到 TRTC 的开发实践,Demo 演示& IM 服务搭建。
音乐音频分类技术能够基于音乐内容为音乐添加类别标签,在音乐资源的高效组织、检索和推荐等相关方面的研究和应用具有重要意义。传统的音乐分类方法大量使用了人工设计的声学特征,特征的设计需要音乐领域的知识,不同分类任务的特征往往并不通用。深度学习的出现给更好地解决音乐分类问题提供了新的思路,本文对基于深度学习的音乐音频分类方法进行了研究。首先将音乐的音频信号转换成声谱作为统一表示,避免了手工选取特征存在的问题,然后基于一维卷积构建了一种音乐分类模型。
C++知识精讲16 | 井字棋游戏(配资源+视频)【赋源码,双人对战】
本文主要讲解如何在Java中,使用FFmpeg进行视频的帧读取,并最终合并成Gif动态图。
在本篇博文中,我们谈及了 Swift 中 some、any 关键字以及主关联类型(primary associated types)的前世今生,并由浅及深用简明的示例向大家讲解了它们之间的奥秘玄机。