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

news2025/2/27 4:57:53

在这里插入图片描述

概览

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

在这里插入图片描述

在这里,我们就和 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)两种集合类型。

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

感谢观赏,再会!😎

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

政安晨:【深度学习处理实践】(四)—— 实施一个温度预测示例

在开始使用像黑盒子一样的深度学习模型解决温度预测问题之前&#xff0c;我们先尝试一种基于常识的简单方法。 它可以作为一种合理性检查&#xff0c;还可以建立一个基准&#xff0c;更高级的机器学习模型需要超越这个基准才能证明其有效性。对于一个尚没有已知解决方案的新问…

从零开始:神经网络(1)——神经元和梯度下降

声明&#xff1a;本文章是根据网上资料&#xff0c;加上自己整理和理解而成&#xff0c;仅为记录自己学习的点点滴滴。可能有错误&#xff0c;欢迎大家指正。 一. 神经网络 1. 神经网络的发展 先了解一下神经网络发展的历程。从单层神经网络&#xff08;感知器&#xff09;开…

【Java网络编程】TCP核心特性(下)

1. 拥塞控制 拥塞控制&#xff1a;是基于滑动窗口机制下的一大特性&#xff0c;与流量控制类似都是用来限制发送方的传送速率的 区别就在于&#xff1a;"流量控制"是从接收方的角度出发&#xff0c;根据接收方剩余接收缓冲区大小来动态调整发送窗口的&#xff1b;而…

【编译原理】1、python 实现一个 JSON parser:lex 词法分析、parser 句法分析

文章目录 一、实现 JSON lexer&#xff08;词法解析器&#xff09;二、lex 词法分析2.1 lex string 解析2.2 lex number 解析2.3 lex bool 和 null 解析 三、syntax parser 句法分析3.1 parse array 解析数组3.2 parse object 解析对象 四、封装接口 一、实现 JSON lexer&#…

论文阅读:Diffusion Model-Based Image Editing: A Survey

Diffusion Model-Based Image Editing: A Survey 论文链接 GitHub仓库 摘要 这篇文章是一篇基于扩散模型&#xff08;Diffusion Model&#xff09;的图片编辑&#xff08;image editing&#xff09;方法综述。作者从多个方面对当前的方法进行分类和分析&#xff0c;包括学习…

时间感知自适应RAG(TA-ARE)

原文地址&#xff1a;Time-Aware Adaptive RAG (TA-ARE) 2024 年 3 月 1 日 介绍 随着大型语言模型&#xff08;LLM&#xff09;的出现&#xff0c;出现了新兴能力的概念。前提或假设是LLMs具有隐藏的和未知的能力&#xff0c;等待被发现。企业家们渴望在LLMs中发现一些无人知晓…

LLM实施的五个阶段

原文地址&#xff1a;Five Stages Of LLM Implementation 大型语言模型显着提高了对话式人工智能系统的能力&#xff0c;实现了更自然和上下文感知的交互。这导致各个行业越来越多地采用人工智能驱动的聊天机器人和虚拟助手。 2024 年 2 月 20 日 介绍 从LLMs的市场采用情况可以…

Day26:安全开发-PHP应用模版引用Smarty渲染MVC模型数据联动RCE安全

目录 新闻列表 自写模版引用 Smarty模版引用 代码RCE安全测试 思维导图 PHP知识点&#xff1a; 功能&#xff1a;新闻列表&#xff0c;会员中心&#xff0c;资源下载&#xff0c;留言版&#xff0c;后台模块&#xff0c;模版引用&#xff0c;框架开发等 技术&#xff1a;输…

超分辨率(1)--基于GAN网络实现图像超分辨率重建

目录 一.项目介绍 二.项目流程详解 2.1.数据加载与配置 2.2.构建生成网络 2.3.构建判别网络 2.4.VGG特征提取网络 2.5.损失函数 三.完整代码 四.数据集 五.测试网络 一.项目介绍 超分辨率&#xff08;Super-Resolution&#xff09;&#xff0c;简称超分&#xff08…

React组件(函数式组件,类式组件)

函数式组件 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>React Demo</title> <!-- 引…

嵌入式Linux串口和 poll() 函数的使用

一、poll() 函数的介绍 poll() 函数用于监控多个文件描述符的变化的函数。它可以用来检查一个或多个文件描述符的状态是否改变&#xff0c;比如是否可读、可写或有错误发生。它常用于处理 I/O 多路复用&#xff0c;这在需要同时处理多个网络连接或文件操作时非常有用。 头文件…

ZJUBCA研报分享 | 《BTC/USDT周内效应研究》

ZJUBCA研报分享 引言 2023 年 11 月 — 2024 年初&#xff0c;浙大链协顺利举办为期 6 周的浙大链协加密创投训练营 &#xff08;ZJUBCA Community Crypto VC Course&#xff09;。在本次训练营中&#xff0c;我们组织了投研比赛&#xff0c;鼓励学员分析感兴趣的 Web3 前沿话题…

【杂记】IDEA和Eclipse如何查看GC日志

1.Eclipse查看GC日志 1.1 右击代码编辑区 -> Run As -> Run Configurations 1.2 点击Arguments栏 -> VM arguments:区域填写XX参数 -> Run 1.3 控制台输出GC详细日志 2.IDEA查看GC日志 2.1 鼠标右击代码编辑器空白区域&#xff0c;选择Edit 项目名.main()... 2.…

IPsec VPN之安全联盟

一、何为安全联盟 IPsec在两个端点建立安全通信&#xff0c;此时这两个端点被称为IPsec对等体。安全联盟&#xff0c;即SA&#xff0c;是指通信对等体之间对某些要素的约定&#xff0c;定义了两个对等体之间要用何种安全协议、IP报文的封装方式、加密和验证算法。SA是IPsec的基…

【JavaEE初阶 -- 多线程】

认识线程&#xff08;Thread&#xff09;Thread类及常见方法 1.认识线程&#xff08;Thread&#xff09;1.1 线程1.2 进程和线程的关系和区别1.3 Java的线程和操作系统线程的关系1.4 创建线程 2. Thread类及常用的方法2.1 Thread的常见构造方法2.2 Thread的几个常见属性2.3 启动…

在 Python 中 JSON 数据格式的使用

在 Python 中 JSON 数据格式的使用 JSON 简介 JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式。它易于阅读和编写&#xff0c;并且与许多编程语言兼容。 Python 中的 JSON 模块 Python 标准库中包含一个 json 模块&#xff0c;用于处理…

docker-compose这下会用了吗?

概要 默认的模板文件是 docker-compose.yml&#xff0c;其中定义的每个服务可以通过 image 指令指定镜像或 build 指令&#xff08;需要 Dockerfile&#xff09;来自动构建。 注意如果使用 build 指令&#xff0c;在 Dockerfile 中设置的选项(例如&#xff1a;CMD, EXPOSE, V…

Normalizer(归一化)和MinMaxScaler(最小-最大标准化)的区别详解

1.Normalizer&#xff08;归一化&#xff09;&#xff08;更加推荐使用&#xff09; 优点&#xff1a;将每个样本向量的欧几里德长度缩放为1&#xff0c;适用于计算样本之间的相似性。 缺点&#xff1a;只对每个样本的特征进行缩放&#xff0c;不保留原始数据的分布形状。 公式…

IM6ULL学习总结(四-七-1)输入系统应用编程

第7章 输入系统应用编程 7.1 什么是输入系统 ⚫ 先来了解什么是输入设备&#xff1f; 常见的输入设备有键盘、鼠标、遥控杆、书写板、触摸屏等等,用户通过这些输入设备与 Linux 系统进行数据交换。 ⚫ 什么是输入系统&#xff1f; 输入设备种类繁多&#xff0c;能否统一它们的…

java 数据结构二叉树

目录 树 树的概念 树的表示形式 二叉树 两种特殊的二叉树 二叉树的性质 二叉树的存储 二叉树的基本操作 二叉树的遍历 二叉树的基本操作 二叉树oj题 树 树是一种 非线性 的数据结构&#xff0c;它是由 n &#xff08; n>0 &#xff09;个有限结点组成一个具有层次…