当前位置: 首页>>编程示例 >>用法及示例精选 >>正文


Swift Collection用法及代码示例

协议

Collection

一个序列,其元素可以被多次、非破坏性地遍历,并且可以通过索引下标访问。

声明

protocol Collection<Element> : Sequence

概述

集合在整个标准库中被广泛使用。当您使用数组、字典和其他集合时,您将从 Collection 协议声明和实现的操作中受益。除了集合从 Sequence 协议继承的操作之外,您还可以访问依赖于访问集合中特定位置的元素的方法。

例如,如果您只想打印字符串中的第一个单词,您可以搜索第一个空格的索引,然后创建一个直到该位置的子字符串。


let text = "Buffalo buffalo buffalo buffalo."
if let firstSpace = text.firstIndex(of: " ") {
    print(text[..<firstSpace])
}
// Prints "Buffalo"

firstSpace 常量是text 字符串的索引——字符串中第一个空格的位置。您可以将索引存储在变量中,并将它们传递给集合算法或稍后使用它们来访问相应的元素。在上面的示例中,firstSpace 用于提取包含直到该索引的元素的前缀。

访问单个元素

您可以使用集合的endIndex 属性以外的任何有效索引,通过其下标访问集合的元素。此属性是一个“past the end” 索引,它与集合的任何元素都不对应。

下面是一个通过下标访问字符串中第一个字符的示例:


let firstChar = text[text.startIndex]
print(firstChar)
// Prints "B"

Collection 协议声明并提供了许多操作的默认实现,这些操作依赖于可通过其下标访问的元素。例如,您还可以使用first 属性访问text 的第一个字符,该属性具有集合的第一个元素的值,或者如果集合为空,则为nil


print(text.first)
// Prints "Optional("B")"

您只能将有效索引传递给集合操作。您可以通过从集合的startIndex 属性开始并查找直到(包括)endIndex 属性的每个后继来找到一组完整的集合有效索引。 Index 类型的所有其他值,例如不同集合的startIndex 属性,都是此集合的无效索引。

由于变异操作,保存的索引可能会变得无效。有关可变集合中索引失效的更多信息,请参阅MutableCollectionRangeReplaceableCollection 协议以及您正在使用的特定类型的参考。

访问集合的切片

您可以通过其范围下标或调用 prefix(while:)suffix(_:) 等方法来访问集合的切片。集合的切片可以包含零个或多个原始集合的元素,并共享原始集合的语义。

下面的示例通过使用prefix(while:) 方法创建firstWord 常量来获取text 字符串的一部分。


let firstWord = text.prefix(while: { $0 != " " })
print(firstWord)
// Prints "Buffalo"

您可以使用字符串的范围下标检索相同的切片,该下标采用范围表达式。


if let firstSpace = text.firstIndex(of: " ") {
    print(text[..<firstSpace]
    // Prints "Buffalo"
}

text 的检索切片在每种情况下都是等效的。

切片股票指数

集合及其切片共享相同的索引。集合的元素位于切片中与基本集合中相同的索引下,只要集合和切片自切片创建以来都没有发生突变。

例如,假设您有一个数组,其中包含一个会话期间每个类的缺勤次数。


var absences = [0, 2, 0, 4, 0, 3, 1, 0]

你的任务是找出下半场缺勤最多的一天。要查找相关日期的索引,请执行以下步骤:

  1. 创建包含后半天的absences 数组的切片。

  2. 使用max(by:) 方法确定缺勤次数最多的一天的索引。

  3. 使用在步骤 2 中找到的原始 absences 数组上的索引打印结果。

以下是这些步骤的实现:


let secondHalf = absences.suffix(absences.count / 2)
if let i = secondHalf.indices.max(by: { secondHalf[$0] < secondHalf[$1] }) {
    print("Highest second-half absences: \(absences[i])")
}
// Prints "Highest second-half absences: 3"

切片继承集合语义

切片继承其基本集合的值或引用语义。也就是说,当使用具有值语义的可变集合的切片(例如数组)时,改变原始集合会触发该集合的副本,并且不会影响切片的内容。

例如,如果您将 absences 数组的最后一个元素从 0 更新为 2 ,则 secondHalf 切片保持不变。


absences[7] = 2
print(absences)
// Prints "[0, 2, 0, 4, 0, 3, 1, 2]"
print(secondHalf)
// Prints "[0, 3, 1, 0]"

遍历集合

尽管可以在遍历序列时使用它,但可以保证集合是 multipass :任何元素都可以通过保存其索引来重复访问。此外,集合的索引构成了集合元素位置的有限范围。所有集合都是有限的这一事实保证了许多序列操作的安全性,例如使用contains(_:) 方法来测试集合是否包含元素。

按位置迭代集合的元素会产生相同的元素,其顺序与使用其迭代器迭代该集合的顺序相同。此示例演示了字符串的 characters 视图以相同的顺序返回相同的字符,无论是迭代视图的索引还是视图本身。


let word = "Swift"
for character in word {
    print(character)
}
// Prints "S"
// Prints "w"
// Prints "i"
// Prints "f"
// Prints "t"


for i in word.indices {
    print(word[i])
}
// Prints "S"
// Prints "w"
// Prints "i"
// Prints "f"
// Prints "t"

符合收集协议

如果您创建一个可以提供对其元素的重复访问的自定义序列,请确保其类型符合Collection 协议,以便为序列和集合操作提供更有用和更有效的接口。要将Collection 一致性添加到您的类型,您必须至少声明以下要求:

  • startIndexendIndex 属性

  • 至少提供对类型元素的只读访问权限的下标

  • index(after:) 将索引推进到集合中的方法

预期表现

符合 Collection 的类型应提供 startIndexendIndex 属性和对元素的下标访问,作为 O(1) 操作。不能保证这种性能的类型必须记录偏离,因为许多收集操作依赖于 O(1) 下标性能来保证它们自己的性能。

某些集合操作的性能取决于集合提供的索引类型。例如,可以在 O(1) 时间内测量两个索引之间的距离的随机访问集合可以在 O(1) 时间内计算其count 属性。相反,由于前向或双向集合必须遍历整个集合以计算包含元素的数量,因此访问其count 属性是 O(n) 操作。

可用版本

iOS 8.0+, iPadOS 8.0+, macOS 10.10+, Mac Catalyst 13.0+, tvOS 9.0+, watchOS 2.0+

相关用法


注:本文由纯净天空筛选整理自apple.com大神的英文原创作品 Collection。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。