Swift 入门学习:集合(Collection)类型趣谈-上

在这里插入图片描述

概览

集合的概念在任何编程语言中都占有重要的位置,正所谓:“古来聚散地,宿昔长荆棘;游人聚散中,一片湖光里”。把那一片片、一瓣瓣、一粒粒“可耐”的小精灵全部收拢、吸纳的井然有序、条条有理,怎能不让我们满心欢喜呢?

在这里插入图片描述

在这里,我们就和 Swift 语言刚入门的小伙伴们一起来闲聊一番关于集合有趣的内容吧。

在本篇博文中,您将学到如下内容:

  • 概览
  • 1. 数据总动员:集合!
  • 2. 数组
  • 3. 字典
  • 总结

在下篇中,我们将继续介绍更多的集合类型,以及其它集合类型有趣的扩展知识。

Swift 中集合的概念简约却不简单,那还等什么呢?

Let’s collect it now!!!😉


1. 数据总动员:集合!

Swift 语言以其独有的简洁、安全、现代化等特性迅速吸引着众多已秃和还未秃的小码农们!在 Swift 语言标准库中包含了 3 种“著名”的集合类型(Collection Types),它们分别是:Array、Dictionary 和 Set。

在这里插入图片描述

在 Swift 中之所以认为它们是集合类型,是因为它们都遵守了 Collection 协议:
在这里插入图片描述

而 Collection 又遵守着 Sequence 协议,环环相套、生生不息。

在 Swift 语言中,集合的本质是容器,里面存放着有序或无序的元素。而遵守 Collection 协议的一大好处是只需实现简单几个属性和方法,我们即可免费获得全套海量通用的集合操作,比如:map()、randomElement()、prefix() 方法等等。

其中,一些方法实际是否适用还要看集合元素的“脸色”,比如下面这些方法就要求方法元素类型遵守 Equatable 协议:

func contains<C>(C) -> Bool
func firstIndex(of: Self.Element) -> Self.Index?
func split(separator: Self.Element, maxSplits: Int, omittingEmptySubsequences: Bool) -> [Self.SubSequence]

其实,小伙伴们可能不知道的是:如果遵守 Collection 协议的类型都算集合,恐怕在 Swift 中符合条件的类型得有一个“加强连”:

遵守 Collection 的类型:

AnyBidirectionalCollection
AnyCollection
AnyRandomAccessCollection
AnyRegexOutput
Array
ArraySlice
ClosedRange
Conforms when Bound conforms to Strideable and Bound.Stride conforms to SignedInteger.
CollectionDifference
CollectionOfOne
ContiguousArray
DefaultIndices
Conforms when Elements conforms to BidirectionalCollection.
Dictionary
Conforms when Key conforms to Hashable.
Dictionary.Keys
Conforms when Key conforms to Hashable.
Dictionary.Values
Conforms when Key conforms to Hashable.
EmptyCollection
FlattenSequence
Conforms when Base conforms to BidirectionalCollection and Base.Element conforms to BidirectionalCollection.
Int.Words
Int16.Words
Int32.Words
Int64.Words
Int8.Words
KeyValuePairs
LazyDropWhileSequence
Conforms when Base conforms to Collection.
LazyFilterSequence
Conforms when Base conforms to BidirectionalCollection.
LazyMapSequence
Conforms when Base conforms to RandomAccessCollection.
LazyPrefixWhileSequence
Conforms when Base conforms to BidirectionalCollection.
LazySequence
Conforms when Base conforms to RandomAccessCollection.
Range
Conforms when Bound conforms to Strideable and Bound.Stride conforms to SignedInteger.
Repeated
ReversedCollection
Conforms when Base conforms to RandomAccessCollection.
Set
Conforms when Element conforms to Hashable.
Slice
Conforms when Base conforms to RandomAccessCollection.
String
String.UTF16View
String.UTF8View
String.UnicodeScalarView
Substring
Substring.UTF16View
Substring.UTF8View
Substring.UnicodeScalarView
UInt.Words
UInt16.Words
UInt32.Words
UInt64.Words
UInt8.Words
Unicode.Scalar.UTF16View
Unicode.Scalar.UTF8View
UnsafeBufferPointer
UnsafeMutableBufferPointer
UnsafeMutableRawBufferPointer
UnsafeRawBufferPointer

这里列这么一大坨实在不是想吓跑各位天真的小伙伴们,只是单纯的想列出来而已~ 😦

除了最常用的 Array、Set 和 Dictionary 三个集合类型之外,我们还将介绍一个有趣的 Range 类型,使用它我们可以描述无限的大集合。


如果觉得上面这些集合类型“一个都不能打”,我们也可以自行动手创建自定义集合类型,你猜对了:就是遵守 Collection 协议即可!

由于篇幅所限,创建自定义集合的话题不在本文范围之内,有缘会在随后的博文中与大家相见。


2. 数组

数组(Array)是很常见的集合类型:

在这里插入图片描述

在 Swift 中数组其实就是一个遵守 Collection 协议的泛型结构。我们可以用多种方法来创建数组:

var ary0 = Array<Int>()
var ary1 = [Int]()
var ary2: [Int] = []

let ary3 = [Int](repeating: 0, count: 100)
let ary4 = [1,2,3,4,5]
let ary5 = Array((0..<100))

如上,我们变着花似地创建了 6 个整数(Int)数组,其中前三个是可变数组,后三个是不可变数组,或者称为只读数组。

我们可以在创建时为数组赋值,或者随后再动态插入新的元素:

var ary = [Int]()
for i in 0..<100{
    ary.append(i*i)
}

如果可能,还是尽量在数组创建时就“填满它”,这样会更具效率。而且在数组尾部新增元素比头部会快更多!

更多数组性能的优化秘技请大家参考如下链接:

  • 你敢信!?几行代码让Swift数组初始化提速400多倍!
  • SwiftUI一招让List巨量数据刷新UI速度快100+倍

我们可以在数组上应用多种方法:

let ary = Array((0..<100))
// 整数数组元素求和
let total = ary.reduce(0) { $0 + $1 }
// 将整数数组转换为字符串数组
let stringAry = ary.map {String($0)}

let neg_ary = -100..<0
// 组合两个数组
let zip_ary = zip(ary, neg_ary).map {[$0*$0, $1]}

因为在 Swift 语言中,数组被实现为结构而非类,由于结构的值拷贝特质:copy 后的数组和原数组就“再无瓜葛了,我们可以随心所欲的改变它而不影响前者:

var ary0 = [1,2,3]
var ary1 = ary0
ary1[0] = -1

print([ary0, ary1])
// 输出: [[1, 2, 3], [-1, 2, 3]]

不过,上面说的这种 copy 又称之为“浅拷贝”,这意味着如果数组元素为引用类型,那么它们的改变仍然会影响新旧两个数组,使用时请尤其留意:

在这里插入图片描述

在上面的代码中,我们改变了新数组中第一个元素的内容,原数组的对应元素也发生了改变。这是因为其元素的类型是 NSMutableString,它是一个引用类型。数组浅拷贝只是 copy 它们的引用,所以实际上它们的改变“所有人都逃不了干系”。

除了普通的数组以外,还存在一种“奇懒无比”的惰性数组:LazySequence。

在这里插入图片描述

其实它应该被称为“惰性序列”,因为它更像一种序列(Sequence)。其包含的每个元素都只在需要时才会被求值,我们会在随后介绍 Range 类型时对 LazySequence 做更进一步的说明。

3. 字典

聊完了数组之后,我们再来与字典(Dictionary)打声招呼吧:

在这里插入图片描述

字典是描述键值(Key-Value)对应关系的一种集合容器。从上面字典的定义中可以看到其键类型必须遵守 Hashable 协议。仔细想想也是蛮有道理的:如若不然,怎么区别字典中键的唯一性呢?

如您所愿,我们同样可以用各种千姿百态的“姿势”来创建字典:

let dict0 = ["A": 0xa, "B": 0xb, "C": 0xc]
var dict1 = [String: Int]()
var dict2: [String: Int] = [:]
var dict3 = Dictionary<String,Int>()

dict2["Panda"] = 11
dict2["Hopy"] = 121

与数组类似,我们可以轻松的遍历字典中的所有键和值:

let dict = ["A": 0xa, "B": 0xb, "C": 0xc]

for key in dict.keys {
    // 单独遍历所有键
}

for value in dict.values {
    // 单独遍历所有值
}

for (key,value) in dict {
    // 同时遍历键和值
    print("\(key):\(value)")
}

let total = dict.reduce("") {$0 + $1.key}

不过字典是无序的,所以不能期望遍历时它们的顺序保存稳定。实际上,依赖于字典元素间顺序的代码逻辑都是错误的,比如上面最后一行代码。

由于无法保证键一定有对应的值,所以通过字典键访问值的结果将会是一个可选类型,我们可以适时的为字典琢磨出一个默认值:

let dict = ["A": 0xa, "B": 0xb, "C": 0xc]

// value 的类型为 Int?
let value = dict["A"]
// 为字典设置默认值
let concreteValue = dict["Z"] ?? 0

总结

在上篇的学习中,我们讨论了 Swift 中集合背后的 Collection 协议,并随后介绍了数组(Array)和字典(Dictionary)两种集合类型。

在下篇中,我们将继续集合大冒险,探索更多的集合类型。

感谢观赏,再会!😎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/443688.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++专栏】C++入门 | 函数重载、引用、内联函数

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;C专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ C入门 | 函数重载、引用、内联函数 文章编号&#xff1a;C入门 / 02 文…

【机器学习】在Python中进行K-Means聚类和层次聚类

Python中聚类算法API的使用指南 聚类分析是数据分析中一种常见的无监督学习方法&#xff0c;通过将相似的对象分组在一起&#xff0c;我们能够识别出数据集中的自然分群。本文将介绍如何使用Python中的聚类算法接口&#xff0c;KMeans和层次聚类方法。 K-Means 聚类 K-Means…

利用 Redis 和 Lua 实现高效的限流功能

简介 在现代系统中&#xff0c;限流是一种重要的机制&#xff0c;用于控制服务端的流量并保护系统免受恶意攻击或请求泛滥的影响。本文将介绍如何利用 Redis 和 Lua 结合实现高效的限流功能。 一、什么是限流 限流指的是对系统中的请求进行控制和调节&#xff0c;确保系统在…

动手学深度学习PyTorch版

基本的数据操作 import torch # 创建一个行向量&#xff0c;默认为从0开始的12个整数 # n维数组也称为张量 x torch.arange(12) x # 张量的形状 x.shape# 张量的大小,张量所有元素的个数 x.numel()#修改张量的形状 x x.reshape(3,4)#生成形状为3*4的两个向量&#xff0c;向…

离散数学——(4)

目录 1.主析取范式 2.大项 3.主合区范式 4.范式的求法 真值表法 5.推理理论 直接证法 1.主析取范式 2.大项 3.主合区范式 4.范式的求法 真值表法 5.推理理论 直接证法

验证码安全

目录 验证码识别&复用&调用&找回密码重定向&状态值 res 修改-找回密码修改返回状态值判定验证通过 验证码爆破-知道验证码规矩进行无次数限制爆破 短信轰炸原理 验证码识别&复用&调用&找回密码重定向&状态值 res 修改-找回密码修改返回状态…

GraalVM 虚拟机-概述

GraalVM 虚拟机 Graal 编译器以及由此诞生的GraalVM&#xff0c;虽然目前还处在实验阶段&#xff0c;但是也是 Java 程序员们必须要了解的&#xff0c;因为他未来极有可能替代 HotSpot&#xff0c;成为 Java生态的下一代技术基础。 1 、关于 Graal Graal编译器最早是作为 Ho…

kamailio转发电话到目的地,目的返回失败时再转给其他IP

按图中这样测试&#xff1a; A---->kamailio------->B B返回480等失败错误码&#xff08;非200 OK&#xff09;&#xff0c;能进入failure_route[TOVOICEMAIL]&#xff0c;但是t_relay_to_udp执行失败。 好吧&#xff0c;说是&#xff1a;在 failure_route 中处理的是…

【嵌入式高级C语言】11:C语言Makefile

文章目录 1 makefile的概述【只针对Linux有效】1.1 make1.2 makefile1.3 采用makefile的好处 2 Makefile的语法规则3 makefile变量3.1 自定义变量3.2 系统环境变量3.3 预定义变量 4 伪目标5 最终版本Makefile 1 makefile的概述【只针对Linux有效】 1.1 make make是个命令&…

这是谁的女儿?其母亲早已红过头了,现在小小年纪的她也爆红网络,没想到吧?

这是谁的女儿&#xff1f;其母亲早已红过头了&#xff0c;现在小小年纪的她也爆红网络&#xff0c;没想到吧&#xff1f; 原来&#xff0c;作母亲的她在红极一时后似乎沉寂了下来&#xff0c;没想到她11岁的女儿近年来也在社交媒体上走红&#xff0c;她为何也成了小网红呢&…

【蓝牙协议栈】【经典蓝牙】【BLE蓝牙】蓝牙协议规范(HCI、L2CAP、SDP、RFOCMM)

目录 1. 蓝牙协议规范&#xff08;HCI、L2CAP、SDP、RFOCMM&#xff09; 1.1 主机控制接口协议 HCI 1.2 逻辑链路控制与适配协议 L2CAP 1.3 服务发现协议SDP 1.4 串口仿真协议 RFCOMM 1. 蓝牙协议规范&#xff08;HCI、L2CAP、SDP、RFOCMM&#xff09; 1.1 主机控制接口协…

寒假作业Day 08

寒假作业Day 08 一、选择题 1、下列关于 const 和 #define 定义常量的区别&#xff0c;说法不正确的有&#xff08; &#xff09; A: define宏是在预处理阶段展开。const常量是编译运行阶段使用 B: 宏没有类型&#xff0c;不做任何类型检查&#xff0c;仅仅是展开。const常量…

计算机找不到api-ms-win-core-path-l1-1-0的5种解决方法

在计算机使用过程中&#xff0c;我们可能会遇到各种问题&#xff0c;其中之一就是找不到某些系统文件。最近&#xff0c;许多用户反映他们在使用电脑时遇到了“找不到api-ms-win-core-path-l1-1-0文件”的问题。这个问题通常出现在Windows操作系统中&#xff0c;可能会影响到一…

【Linux】编译器-gcc/g++使用

个人主页 &#xff1a; zxctscl 文章封面来自&#xff1a;艺术家–贤海林 如有转载请先通知 文章目录 1. 前言2. 初见gcc和g3. 程序的翻译过程3.1 预处理3.1.1 宏替换 去注释 头文件展开3.1.2 条件编译 3.2 编译3.3 汇编3.4 链接 4. 链接4.1 动态链接4.2 静态链接 1. 前言 在之…

DRC:扩散模型的推荐系统应用

1 Title Diffusion Recommender Model&#xff08;Wenjie Wang、Yiyan Xu、Fuli Feng、Xinyu Lin、Xiangnan He、Tat-Seng Chua&#xff09;【SIGIR 23】 2 Conclusion . In light of the impressive advantages of Diffusion Models (DMs) over traditional generative model…

万字完整版【C语言】指针详解~

一、前言 初始指针&#xff08;0&#xff09;&#xff1a;着重于讲解指针的概念、基本用法、注意事项、以及最后如何规范使用指针深入指针&#xff08;1&#xff09;&#xff1a;讲解指针变量常见的类型&#xff0c;如何去理解这些类型、最后就是如何正确的使用深入指针&#…

【语法基础练习】1.变量、输入输出、表达式与顺序语句

&#x1f338;博主主页&#xff1a;釉色清风&#x1f338;文章专栏&#xff1a;算法练习&#x1f338;今日语录&#xff1a;You don’t know until you try. 文章简介&#xff1a;下面的题目是AcWing网站语法基础练习篇的第一小节&#xff0c;内容基础&#xff0c;难度&#xf…

如何进入Windows 11的安全模式?这里提供详细步骤

序言 如果你在启动Windows 11 PC时遇到问题,则重新启动到安全模式可能会有所帮助,该模式会暂时禁用驱动程序和功能,以使你的PC更稳定。下面是如何做到这一点。 在Windows 7和更早版本中,通常可以在打开电脑后按功能键(如F8)启动安全模式。Microsoft从Windows 8中删除了…

MybatisPlus知识点总结(基于黑马2023MybatisPlus课程)

MybatisPlus知识点总结 配套资料 黑马微服务框架笔记&#xff0c;内含mpMybatisPlus.pptxMyBatis-Plus &#xff08;mp中文官网&#xff09; 快速入门 入门案例 使用MybatisPlus的基本步骤&#xff1a;1.引入MybatisPlus依赖&#xff0c;代替Mybatis依赖2.定义Mapper接口并继…

C++_可变参数模板

目录 1、可变参数模板的用法 2、参数包展开 2.1 递归方式展开 2.2 逗号表达式形式展开 3、参数包的大小 结语 前言&#xff1a; C11引入了可变参数模板&#xff0c;他的作用是可以让创建的函数模板或者类模板的模板参数可以接收任意数量参数&#xff0c;在C11前&#x…