Swift 中的数据结构 - 第一部分
介绍
为什么要使用数据结构?
数据结构是保存程序中使用的数据的容器。这些数据结构的效率会影响整个软件。因此,了解可供我们使用的结构器并为各种任务选择正确的结构器至关重要。
结构
这是有关 Swift 中数据结构的两部分系列文章的第一部分。
在本教程中,我们将讨论泛型和内置的 Swift 集合类型。在第二部分中,我们将介绍一些最流行的数据结构以及如何在 Swift 中实现它们。
泛型
泛型是编写有用且可重用代码的手段。它们还用于实现不局限于单一数据类型的灵活数据结构。
泛型是 Swift 标准库的核心。它们深深扎根于语言之中,你不能也不应该忽视它们。事实上,一段时间后,你甚至不会注意到你正在使用泛型。
为什么我们需要泛型?
为了说明这个问题,让我们尝试解决一个简单的问题:创建包含不同值对的类型。
一种简单的尝试可能是这样的:
struct StringPair {
var first: String
var second: String
}
struct IntPair {
var first: Int
var second: Int
}
struct FloatPair {
var first: Float
var second: Float
}
现在,如果我们需要一个包含 Data 实例对的类型怎么办?没问题,我们将创建一个 DataPair 结构!
struct DataPair {
var first: Data
var second: Data
}
那么,如果有一个类型包含不同的类型,比如 String 和 Double,那怎么办呢?如下所示:
struct StringDoublePair {
var first: String
var second: Double
}
我们现在可以使用我们新创建的类型:
let pair = StringPair(first: "First", second: "Second")
print(pair)
// StringPair(first: "First", second: “Second")
let numberPair = IntPair(first: 1, second: 2)
print(numberPair)
// IntPair(first: 1, second: 2)
let stringDoublePair = StringDoublePair(first: "First", second: 42.5)
print(stringDoublePair)
// StringDoublePair(first: "First", second: 42.5)
这真的是可行的方法吗?绝对不行!我们必须在类型爆炸失控之前阻止它。
泛型类型
如果只有一种类型可以处理任意值,那不是很酷吗?那就这样吧:
struct Pair<T1, T2> {
var first: T1
var second: T2
}
我们找到了一个可以用于任何类型的通用解决方案。
我们不提供结构中属性的具体类型,而是使用占位符:T1 和 T2。
我们可以简单地调用我们的结构Pair,因为我们不必在结构名称中指定支持的类型。
现在我们可以写:
let floatFloatPair = Pair<Float, Float>(first: 0.3, second: 0.5)
print(floatFloatPair)
// Pair<Float, Float>(first: 0.300000012, second: 0.5)
我们甚至可以跳过占位符类型,因为编译器足够智能,可以根据参数确定类型。(类型推断通过在编译代码时检查提供的值来工作。)
let stringAndString = Pair(first: "First String", second: "Second String")
print(stringAndString)
// Pair<String, String>(first: "First String", second: "Second String")
let stringAndDouble = Pair(first: "I'm a String", second: 99.99)
print(stringAndDouble)
// Pair<String, Double>(first: "I\'m a String", second: 99.989999999999995)
let intAndDate = Pair(first: 42, second: Date())
print(intAndDate)
// Pair<Int, Date>(first: 42, second: 2017-08-15 19:02:13 +0000)
在 Swift 中,我们可以轻松地定义通用类、结构或枚举。
Swift 集合类型
Swift 有一些主要的集合类型可供我们学习。让我们仔细看看内置的数组、集合和字典类型。
数组
数组以特定顺序存储相同类型的值。值不能是唯一的:每个值可以出现多次。Swift 将数组(以及所有其他集合类型)实现为泛型类型。它们可以存储任何类型:类、结构、枚举的实例,或任何内置类型,如 Int、Float、Double 等。
创建数组
我们使用以下语法创建一个数组:
let numbers: Array<Int> = [0, 2, 1, 3, 1, 42]
print(numbers)
// Output: [0, 2, 1, 3, 1, 42]
您还可以使用简写形式[Type] - 顺便说一下,这是首选形式:
let numbers1: [Int] = [0, 2, 1, 3, 1, 42]
提供元素的类型是可选的:我们还可以依靠 Swift 的类型推断来计算数组的类型:
let numbers = [0, 2, 1, 3, 1, 42]
从零开始的索引标识每个元素的位置。我们可以遍历数组并使用 Array index(of:)实例方法打印索引:
for value in numbers {
if let index = numbers.index(of: value) {
print("Index of \(value) is \(index)")
}
}
输出将是:
Index of 0 is 0
Index of 2 is 1
Index of 1 is 2
Index of 3 is 3
Index of 1 is 2
Index of 42 is 5
我们还可以使用forEach(_:)方法遍历数组。此方法以与 for-in 循环相同的顺序在每个元素上执行其闭包:
numbers.forEach { value in
if let index = numbers.index(of: value) {
print("Index of \(value) is \(index)")
}
}
可变数组
如果我们想在创建数组后修改它,我们必须将其分配给变量而不是常量。
var mutableNumbers = [0, 2, 1, 3, 1, 42]
然后,我们可以使用各种 Array 实例方法(例如append(_:)或insert(_:at:))向数组添加新值。
mutableNumbers.append(11)
print(mutableNumbers)
// Output: [0, 2, 1, 3, 1, 42, 11]
mutableNumbers.insert(100, at: 2)
print(mutableNumbers)
// Output: [0, 2, 100, 1, 3, 1, 42, 11]
如果您使用insert(at:),请确保索引有效,否则您将陷入运行时错误。
要从数组中删除元素,我们可以使用remove(at:)方法:
mutableNumbers.remove(at: 2)
print(mutableNumbers)
// Output: [0, 2, 1, 3, 1, 42, 11]
同样,如果索引无效,则会发生运行时错误。每当我们从数组中删除元素时,间隙就会消失。要删除所有元素,请调用removeAll():
mutableNumbers.removeAll()
print(mutableNumbers)
// Output: []
我已经提到了一些最常用的 Array 方法。还有许多其他方法可供您使用;查看文档或在 Swift Playground 中开始尝试使用它们。
数组按顺序存储相同类型的值。如果元素的顺序很重要,并且相同的值会出现多次,请使用数组。
如果元素的顺序或重复无关紧要,则可以改用集合。
套
集合和数组之间有两个根本区别:
- 该集合没有提供定义的顺序
- 一个值在一个集合中只能出现一次
集合公开了一些有用的方法,让我们可以使用诸如并集和减集之类的数学集合运算来组合两个集合。让我们开始了解集合创建的基本语法。
创建集
我们可以使用以下语法声明一个集合:
let uniqueNumbers: Set<Int> = [0, 2, 1, 3, 42]
print(uniqueNumbers)
// Output: [42, 2, 0, 1, 3]
请注意,我们不能像数组那样使用简写形式。如果我们像这样定义它,Swift 的类型推断引擎就无法判断我们是否要实例化 Set 而不是数组:
let uniqueNumbers = [0, 2, 1, 3, 42] // this will create an Array of Int values
我们必须指定我们需要一个 Set;但是,类型推断仍然适用于 Set 中使用的值。因此,我们可以编写以下内容:
let uniqueNumbers: Set = [0, 2, 1, 3, 42] // creates a Set of Int values
我们来看看这个例子:
let zeroes: Set<Int> = [0, 0, 0, 0]
print(zeroes)
你能猜出输出结果吗?这是我们在控制台中看到的内容:[0]该集合只允许四个零中的一个。而如果我们使用数组,我们将得到所有零:
let zeroesArray: Array<Int> = [0, 0, 0, 0]
print(zeroesArray)
// Output: [0, 0, 0, 0]
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~