swift笔记-集合

Swift 语言提供经典的数组和字典两种集合类型来存储集合数据。数组用来按顺序存储相同类型的数据。字典虽然无序存储相同类型数据值但是需要由独有的标识符引用和寻址(就是键值对)。

Swift 语言里的数组和字典中存储的数据值类型必须明确。 这意味着我们不能把不正确的数据类型插入其中。 同时这也说明我们完全可以对获取出的值类型非常自信。 Swift 对显式类型集合的使用确保了我们的代码对工作所需要的类型非常清楚,也让我们在开发中可以早早地找到任何的类型不匹配错误。

注意:Swift 的数组结构在被声明成常量和变量或者被传入函数与方法中时会相对于其他类型展现出不同的特性。 获取更多信息请参见集合的可变性集合在赋值和复制中的行为章节。

数组

数组使用有序列表存储同一类型的多个值。相同的值可以多次出现在一个数组的不同位置中。

Swift 数组特定于它所存储元素的类型。这与 Objective-C 的 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 已经被构造并且拥有两个初始项。

shoppingList变量被声明为“字符串值类型的数组“,记作[String]。 因为这个数组被规定只有String一种数据结构,所以只有String类型可以在其中被存取。 在这里,shoppinglist数组由两个String值("Eggs""Milk")构造,并且由字面量定义。

注意:Shoppinglist数组被声明为变量(var关键字创建)而不是常量(let创建)是因为以后可能会有更多的数据项被插入其中。

在这个例子中,字面量仅仅包含两个String值。匹配了该数组的变量声明(只能包含String的数组),所以这个字面量的分配过程就是允许用两个初始项来构造shoppinglist

由于 Swift 的类型推断机制,当我们用字面量构造只拥有相同类型值数组的时候,我们不必把数组的类型定义清楚。 shoppinglist的构造也可以这样写:

var shoppingList = ["Eggs","Milk"]

因为所有字面量中的值都是相同的类型,Swift 可以推断出[String]shoppinglist中变量的正确类型。

访问和修改数组

我们可以通过数组的方法和属性来访问和修改数组,或者下标语法。还可以使用数组的只读属性count来获取数组中的数据项数量。

println("The shopping list contains \(shoppingList.count) items.")
// 输出"The shopping list contains 2 items."(这个数组有2个项)

使用布尔项isEmpty来作为检查count属性的值是否为 0 的捷径。

if shoppingList.isEmpty {
    println("The shopping list is empty.")
} else {
    println("The shopping list is not empty.")
}
// 打印 "The shopping list is not empty."(shoppinglist不是空的)

也可以使用append方法在数组后面添加新的数据项:

shoppingList.append("Flour")
// shoppingList 现在有3个数据项,有人在摊煎饼

除此之外,使用加法赋值运算符(+=)也可以直接在数组后面添加一个或多个拥有相同类型的数据项:

shoppingList += ["Baking Powder"]
// shoppingList 现在有四项了
shoppingList += ["Chocolate Spread","Cheese","Butter"]
// shoppingList 现在有七项了

可以直接使用下标语法来获取数组中的数据项,把我们需要的数据项的索引值放在直接放在数组名称的方括号中:

var firstItem = shoppingList[0]
// 第一项是 "Eggs"

注意第一项在数组中的索引值是0而不是1。 Swift 中的数组索引总是从零开始。

我们也可以用下标来改变某个已有索引值对应的数据值:

shoppingList[0] = "Six eggs"
// 其中的第一项现在是 "Six eggs" 而不是 "Eggs"

还可以利用下标来一次改变一系列数据值,即使新数据和原有数据的数量是不一样的。下面的例子把"Chocolate Spread""Cheese",和"Butter"替换为"Bananas""Apples"

shoppingList[4...6] = ["Bananas","Apples"]
// shoppingList 现在有六项

注意:我们不能使用下标语法在数组尾部添加新项。如果我们试着用这种方法对索引越界的数据进行检索或者设置新值的操作,我们会引发一个运行期错误。我们可以使用索引值和数组的count属性进行比较来在使用某个索引之前先检验是否有效。除了当count等于 0 时(说明这是个空数组),最大索引值一直是count - 1,因为数组都是零起索引。

调用数组的insert(atIndex:)方法来在某个具体索引值之前添加数据项:

shoppingList.insert("Maple Syrup",atIndex: 0)
// shoppingList 现在有7项
// "Maple Syrup" 现在是这个列表中的第一项

这次insert函数调用把值为"Maple Syrup"的新数据项插入列表的最开始位置,并且使用0作为索引值。

类似的我们可以使用removeAtIndex方法来移除数组中的某一项。这个方法把数组在特定索引值中存储的数据项移除并且返回这个被移除的数据项(我们不需要的时候就可以无视它):

let mapleSyrup = shoppingList.removeAtIndex(0)
// 索引值为0的数据项被移除
// shoppingList 现在只有6项,而且不包括Maple Syrup
// mapleSyrup常量的值等于被移除数据项的值 "Maple Syrup"

数据项被移除后数组中的空出项会被自动填补,所以现在索引值为0的数据项的值再次等于"Six eggs":

firstItem = shoppingList[0]
// firstItem 现在等于 "Six eggs"

如果我们只想把数组中的最后一项移除,可以使用removeLast方法而不是removeAtIndex方法来避免我们需要获取数组的count属性。就像后者一样,前者也会返回被移除的数据项:

let apples = shoppingList.removeLast()
// 数组的最后一项被移除了
// shoppingList现在只有5项,不包括cheese
// apples 常量的值现在等于"Apples" 字符串

数组的遍历

我们可以使用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循环的介绍请参见for 循环

创建并且构造一个数组

我们可以使用构造语法来创建一个由特定数据类型构成的空数组:

var someInts = [Int]()
println("someInts is of type [Int] with \(someInts.count) items。")
// 打印 "someInts is of type [Int] with 0 items。"(someInts是0数据项的Int[]数组)

注意someInts被设置为一个[Int]构造函数的输出所以它的变量类型被定义为[Int]

除此之外,如果代码上下文中提供了类型信息, 例如一个函数参数或者一个已经定义好类型的常量或者变量,我们可以使用空数组语句创建一个空数组,它的写法很简单:[](一对空方括号):

someInts.append(3)
// someInts 现在包含一个INT值
someInts = []
// someInts 现在是空数组,但是仍然是[Int]类型的。

Swift 中的Array类型还提供一个可以创建特定大小并且所有数据都被默认的构造方法。我们可以把准备加入新数组的数据项数量(count)和适当类型的初始值(repeatedValue)传入数组构造函数:

var threeDoubles = [Double](count: 3,repeatedValue:0.0)
// threeDoubles 是一种 [Double]数组,等于 [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 被推断为 [Double],2.5]

集合

集合用来存储相同类型并且没有确定顺序的值。当集合元素顺序不重要时或者希望确保每个元素只出现一次时可以把集合当做是数组另一形式。

注意:Swift的Set类型被桥接到Fundation中的NSSet类关于使用FundationCocoa中集合的知识,请看Swift与Cocoa和Objective-C使用

Set类型语法

Swift中的Set类型被写为Set<SomeType>,这里的SomeType表示Set中允许存储的类型,和数组不同的是,集合没有等价的简化形式。

创建和构造一个Set

你可以通过构造器语法创建一个特定类型的空集合:

var letters = Set<Character>()
println("letters is of type Set<Character> with \(letters.count) items.")
// 打印 "letters is of type Set<Character> with 0 items."

注意这里的letters变量的类型来自于构造器的类型,其为Set<Character>

另外,如果上下文提供了类型信息,比如作为函数的参数或者已知类型的变量或常量,你可以通过一个空的数组字面量创建一个空的Set

letters.insert("a")
// letters现在含有1个Character类型的值
letters = []
// letters现在是一个空的Set,但是它依然是Set<Character>类型

集合与数组字面量

你可以使用一个数组字面量来构造一个集合,并且可以使用简化形式写一个或者多个值作为集合元素。

下面的例子创建一个称之为favoriteGenres的集合来存储String类型的值:

var favoriteGenres: Set<String> = ["Rock","Classical","Hip hop"]
// favoriteGenres被构造成含有三个初始值的集合

这个favoriteGenres变量被声明为“一个String值的集合”,写为Set<String>。由于这个特定的集合含有指定String类型的值,所以它只允许存储String类型值。这里的favoriteGenres变量有三个String类型的初始值("Rock","Classical"和"Hip hop"),并以数组字面量的方式出现。

注意:favoriteGenres被声明为一个变量(拥有var标示符)而不是一个常量(拥有let标示符),因为它里面的元素将会在下面的例子中被增加或者移除。

一个Set类型不能从数组中字面量中独立地被推断出来,因此Set类型必须显式声明。然而,由于Swift的类型推导功能,如果你想使用一个数组字面量构造一个Set并且该数组字面量中的所有元素类型相同,那么你无须写出Set的具体类型。favoriteGenres的构造形式可以采用简化的方式代替:

var favoriteGenres: Set = ["Rock","Hip hop"]

由于数组字面量中的所有元素类型相同,Swift可以推断出Set<String>作为favoriteGenres变量的正确类型。

访问和修改一个Set

你可以通过Set的属性和方法来访问和修改一个Set.

为了找出一个Set中元素的数量,可以使用其只读属性count:

println("I have \(favoriteGenres.count) favorite music genres.")
// 打印 ""I have 3 favorite music genres.""

使用布尔属性isEmpty作为一个缩写形式去检查count属性是否为0:

if favoriteGenres.isEmpty {
    println("As far as music goes,I'm not picky.")
} else {
    println("I have particular music preferences.")
}
// 打印 "I have particular music preferences."

你可以通过调用Setinsert(_:)方法添加一个新的元素:

favoriteGenres.insert("Jazz")
// favoriteGenres 现在包含4个元素

你可以通过调用Setremove(_:)方法去删除一个元素,如果该值是该Set的一个元素则删除该元素并且返回被删除的元素值,否认如果该Set不包含该值,则返回nil。另外,Set中的所有元素可以通过它的removeAll()方法删除。

if let removedGenre = favoriteGenres.remove("Rock") {
    println("\(removedValue)? I'm over it.")
} else {
    println("I never much cared for that.")
}
// 打印 "Rock? I'm over it."

使用contains(_:)方法去检查Set中是否包含一个特定的值。

if favoriteGenres.contains("Funk") {
    println("I get up on the good foot.")
} else {
    println("It's too funky in here.")
}
// 打印 "It's too funky in here."

遍历一个Set

你可以在一个for-in循环中遍历一个Set中的所有值。

for genre in favoriteGenres {
    println("\(value)")
}
// Classical
// Jazz
// Hip hop

更多关于for-in循环信息,请看For循环

Swift的Set类型没有确定的顺序,为了按照特定顺序来遍历一个Set中值可以使用全局sorted函数,它将根据提供的序列返回一个排序的集合.

-> for genre in sorted(favoriteGenres) {
    println("\(genre)")
}
// prints "Classical"
// prints "Hip hop"
// prints "Jazz

完成集合操作

你可以高效的完成Set的一些基本操作,比如把两个集合组合到一起,判断两个集合共有元素,或者判断两个集合是否全包含,部分包含或者不相交。

构造集合

下面的插图描述了两个集合-ab-以及通过阴影部分的区域显示集合各种操作的结果。

  • 使用union(_:)方法根据两个集合的值创建一个新的集合。
  • 使用subtract(_:)方法根据不在该集合中的值创建一个新的集合。
  • 使用intersect(_:)方法根据两个集合中都包含的值创建的一个新的集合。
  • 使用exclusiveOr(_:)方法根据值在一个集合中但不在两个集合中的值创建一个新的集合。
let oddDigits: Set = [1,3,5,7,9]
let evenDigits: Set = [0,2,4,6,8]
let singleDigitPrimeNumbers: Set = [2,7]
sorted(oddDigits.union(evenDigits))
// [0,1,2,3,4,5,6,7,8,9]
sorted(oddDigits.intersect(evenDigits))
// []
sorted(oddDigits.subtract(singleDigitPrimeNumbers))
// [1,9]
sorted(oddDigits.exclusiveOr(singleDigitPrimeNumbers))
// [1,9]

集合比较

下面的插图描述了三个集合-a,bc,以及通过悬浮区域表述集合间共享的元素。Set a是Set b的父集合,因为a包含了b中所有的元素,相反的,Set ba的子集合,因为属于b的元素也被a包含。Set b和Set c彼此不关联,因为它们之间没有共同的元素。

  • 使用“是否等”运算符(=)来判断两个集合是否包含相同的值。
  • 使用isSubsetOf(_:)方法来判断一个集合中的值是否也被包含在另外一个集合中。
  • 使用isSupersetOf(_:)方法来判断一个集合中包含的值是另一个集合中所有的值。
  • 使用isStrictSubsetOf(_:)或者isStrictSupersetOf(_:)方法来判断一个集合是否是另外一个集合的子集合或者父集合并且和特定集合不相等。
  • 使用isDisjointWith(_:)方法来判断两个结合是否不含有相同的值。
let houseAnimals: Set = ["  

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 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)的前世今生,并由浅及深用简明的示例向大家讲解了它们之间的奥秘玄机。