ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Swift Algorithms 指南:`suffix(while:)` 从集合尾部按谓词提取后缀子序列

Swift Algorithms 指南:`suffix(while:)` 从集合尾部按谓词提取后缀子序列 开发工具【免费下载链接】swift-algorithmsCommonly used sequence and collection algorithms for Swift项目地址https://gitcode.com/gh_mirrors/swi/swift-algorithms点击查看免费下载suffix(while:)是 Swift Algorithms 开源库README.md中提供的一个子集操作 API它从集合的末尾开始反向扫描返回连续满足给定谓词的所有元素组成的后缀子序列SubSequence一旦谓词返回false便立即停止并跳过更靠前的其余元素。本文以 Guides/Suffix.md 为骨架结合 Sources/Algorithms/Suffix.swift 的实现与 Tests/SwiftAlgorithmsTests/SuffixTests.swift 的测试用例完整讲解它的用法、边界行为、底层原理、复杂度与命名由来。读完本文你将掌握如何用一行代码取出集合末尾满足条件的连续元素并理解它与prefix(while:)、drop家族的异同。核心功能什么是suffix(while:)suffix(while:)返回一个子序列其中包含从集合尾部起、所有连续通过给定谓词predicate检验的元素。扫描自后向前进行从最后一个元素开始逐个向前检验一旦遇到某个元素使谓词返回false扫描立即终止该元素及其之前的全部元素都会被跳过。用原文档中的示例来说明对一个整数集合从尾部向前遍历直到遇到$0 5的元素为止剩下的元素即为结果。(0...10).suffix(while: { $0 5 }) // [6, 7, 8, 9, 10]这里0...10的尾部是1010 5成立继续向前9、8、7、6同样成立遇到5时5 5为false扫描停止返回6...10这个子序列。从源码注释Sources/Algorithms/Suffix.swift可以看到 API 语义的精确定义参数predicate一个以元素为参数、返回Bool的闭包。返回true表示该元素应被包含返回false表示应被排除。一旦谓词返回过一次false它就不会再被调用。返回值集合的一个后缀子序列其中所有元素都使predicate返回true。这个谓词只在前缀/后缀扫描期间被调用的约定很重要——它意味着suffix(while:)是短路的不会为整个集合的每个元素都执行谓词这一点与标准库prefix(while:)的行为一致。基本用法与边界行为在 Tests/SwiftAlgorithmsTests/SuffixTests.swift 的testSuffix()用例中覆盖了四种典型边界情况let a 0...10 expectEqualSequences(a.suffix(while: { $0 5 }), (6...10)) expectEqualSequences(a.suffix(while: { $0 10 }), []) expectEqualSequences(a.suffix(while: { $0 9 }), [10]) expectEqualSequences(a.suffix(while: { $0 -1 }), (0...10)) let empty: [Int] [] expectEqualSequences(empty.suffix(while: { $0 10 }), [])逐条解读这五个用例正好涵盖了所有值得注意的边界场景调用结果说明a.suffix(while: { $0 5 })6...10常规场景尾部连续满足谓词的元素a.suffix(while: { $0 10 })[]尾部第一个元素10就不满足返回空子序列a.suffix(while: { $0 9 })[10]只取到紧邻首个失败元素之后的一个元素a.suffix(while: { $0 -1 })0...10全部元素都满足返回整个集合作为子序列empty.suffix(while: { $0 10 })[]空集合上调用安全返回空子序列不会崩溃这组测试还顺带验证了返回类型是子序列SubSequence而非新数组(6...10)是对原Range的切片视图而不是拷贝出来的Array因此调用suffix(while:)不会产生额外的堆分配。实战示例清理日志中的活跃尾段假设有一段日志数组你想取出最近连续处于活跃状态的记录let log [idle, idle, active, active, active] let activeTail log.suffix(while: { $0 active }) // [active, active, active]或者提取一个数组末尾连续为偶数的一段let numbers [1, 2, 3, 4, 8, 16, 7] let tailEven numbers.suffix(while: { $0.isMultiple(of: 2) }) // [4, 8, 16]注意第二个例子中4之后的8、16都满足而3不满足所以结果只包含4, 8, 16——中间一旦断裂靠前的满足元素同样会被丢弃。详细设计API 签名与协议约束根据 Guides/Suffix.md 的 Detailed Design 一节suffix(while:)作为BidirectionalCollection的扩展方法加入extension BidirectionalCollection { public func suffix(while predicate: (Element) throws - Bool) rethrows - SubSequence }方法声明为rethrows意味着传入的谓词闭包可以抛出错误此时错误会向上传递这也符合 Swift 标准库对这类高阶遍历 API 的一贯约定。为什么必须是BidirectionalCollection该方法之所以要求BidirectionalCollection是为了获得高效实现它能从尾部向前尽量少地访问元素。Swift 的BidirectionalCollection协议允许对集合进行反向遍历并且提供访问集合last属性以及formIndex(before:)的能力。若退化为仅支持Collection的实现只能从startIndex一路遍历到endIndex才能确定后缀的边界代价是始终扫描整个集合。关于这一设计取舍可以参考同仓库的 Guides/Trim.md其中明确指出虽然理论上任何Collection都能实现从尾部裁剪的低效版本总是遍历整个集合但库有意不提供这种实现以免编写泛型算法的开发者忘记添加BidirectionalCollection约束时悄悄得到一个低效版本。suffix(while:)遵循同样的原则——把效率保证写进类型约束里。可直接运行的安装前提要在自己的 SwiftPM 工程中使用该 API按 README.md 的说明在Package.swift中添加依赖.package(url: https://github.com/apple/swift-algorithms, from: 1.2.0),并在目标中声明.product(name: Algorithms, package: swift-algorithms)随后在源码中import Algorithms即可调用suffix(while:)、prefix(while:)等全部算法。本仓库对应的完整清单见 Guides/README.mdsuffix(while:)被归类在Subsetting operations子集操作之下。底层实现剖析Sources/Algorithms/Suffix.swift中suffix(while:)的实现极其简洁只有一行inlinable public func suffix( while predicate: (Element) throws - Bool ) rethrows - SubSequence { try self[startOfSuffix(while: predicate)...] }它的真正逻辑被委托给配套的辅助方法startOfSuffix(while:)其完整实现如下extension BidirectionalCollection { inlinable public func startOfSuffix( while predicate: (Element) throws - Bool ) rethrows - Index { var index endIndex while index ! startIndex { let after index formIndex(before: index) if try !predicate(self[index]) { return after } } return index } }逐行走读这段核心逻辑从endIndex出发把当前游标记为下一个元素after通过formIndex(before: index)回退一步检验该元素是否满足谓词若不满足说明此前已收集到的后缀到此为止返回after即第一个失败元素之后的位置作为后缀子序列的包含下界inclusive lower bound若满足继续向前回退循环直到index startIndex说明全部元素都满足返回startIndex。于是suffix(while:)只需用self[lowerBound...]从找到的下界一路切到endIndex形成切片返回。整个过程中谓词一旦返回false就立刻结束不会再被调用。对称的姊妹 APIendOfPrefix(while:)同一个源文件中还提供了Collection上的endOfPrefix(while:)它从前向后工作返回前缀的排他上界exclusive upper bound即第一个不满足谓词的元素的索引若全部满足则返回endIndexextension Collection { inlinable public func endOfPrefix( while predicate: (Element) throws - Bool ) rethrows - Index { var index startIndex while try index ! endIndex predicate(self[index]) { formIndex(after: index) } return index } }这两个辅助方法最初是trimming系列方法的内部实现细节在 1.2.0 版本中因本身独立有用而被公开为公共 API见 CHANGELOG.md 中 TheendOfPrefix(while:)andstartOfSuffix(while)methods are now public 的记载以及 Guides/Trim.md 的 Supporting Methods 一节。它们的公开也使得查找集合的前缀边界 / 后缀边界成为库的一等能力文档入口见 Sources/Algorithms/Documentation.docc/Trimming.md 中的 Finding Boundaries within a Collection 与 Finding the Suffix of a Collection 两节。endOfPrefix(while:)与startOfSuffix(while:)的行为同样有专门的测试覆盖testEndOfPrefix、testStartOfSuffix见 Tests/SwiftAlgorithmsTests/SuffixTests.swift包括全部满足、全部不满足、空集合等情形例如let array Array(0..10) XCTAssertEqual(array.endOfPrefix(while: { $0 3 }), 3) XCTAssertEqual(array.startOfSuffix(while: { $0 3 }), 3) XCTAssertEqual(array.endOfPrefix(while: { _ in true }), array.endIndex) XCTAssertEqual(array.startOfSuffix(while: { _ in false }), array.endIndex)注意startOfSuffix(while:)在全部不满足时返回endIndex此时后缀为空在全部满足时返回startIndex此时后缀即整个集合——这两个返回值方向相反使用时可结合测试用例对照理解。复杂度分析原文档明确给出调用suffix(while:)的时间复杂度为 O(n)其中n是集合长度Sources/Algorithms/Suffix.swift 的文档注释同样标注了- Complexity: O(*n*)。这里的 O(n) 是最坏情况上界——当所有元素都满足谓词时需要从尾部一路回退到startIndex。但在实际使用中由于算法从尾部短路返回典型开销与被返回后缀之前失败元素的位置成正比失败元素越靠近末尾访问的元素越少。空间上返回值是原集合的切片SubSequence不会复制元素无额外存储开销。命名考量与prefix(while:)的对称原文档的 Naming 一节解释了函数名的由来Swift 标准库已有一个prefix(while:)它对集合做正向遍历返回从头部开始连续满足谓词的前缀suffix(while:)从集合末端反向遍历做的是同一件事因此命名为suffix(while:)与既有 API 形成清晰的镜像对称。标准库中还提供了返回子序列的drop(while:)等价于左侧裁剪以及dropFirst(Int)、dropLast(Int)等无谓词裁剪手段但这些方法都不支持自定义谓词且方向语义各不相同详见 Guides/Trim.md 对drop家族的讨论。suffix(while:)与它们的区别在于它同时具备从尾部开始与谓词控制裁剪点两个能力正好补齐了标准库在右端按条件裁剪上的空缺。小结suffix(while:)从BidirectionalCollection的末端向前扫描返回连续满足谓词的后缀子序列谓词一遇false即停止实现委托给公开的辅助方法startOfSuffix(while:)配合endOfPrefix(while:)共同构成查找集合前后边界的基础工具时间复杂度最坏 O(n)实际开销取决于失败元素的位置返回值为零拷贝切片边界行为空集合、全部满足、首元素即失败均有测试用例佐证可放心在泛型代码中直接使用。如果想进一步了解以这两个辅助方法为地基的trimming系列同时裁剪头部与尾部建议继续阅读 Guides/Trim.md完整的 API 分类索引见 Guides/README.md。赞分享开发工具【免费下载链接】swift-algorithmsCommonly used sequence and collection algorithms for Swift项目地址https://gitcode.com/gh_mirrors/swi/swift-algorithms点击查看免费下载相关推荐DoWhy 箭头强度量化基于 GCM 框架衡量因果直接影响Arrow StrengthDoWhy 箭头强度量化基于 GCM 框架衡量因果直接影响Arrow Strength 导读 本文围绕 DoWhy 的 GCMGraphical Cau开发工具Swift Algorithms前缀后缀处理suffix、trimming和split的实战演练想要掌握Swift序列处理的核心技巧吗 Swift Algorithms库中的suffix、trimming和split方法正是你需要的终极工具这些函数开发工具cp-algorithms 系列后缀自动机Suffix Automaton的原理、线性构建与经典应用实战cp algorithms 系列后缀自动机Suffix Automaton的原理、线性构建与经典应用实战 导读 后缀自动机是字符串处理领域极具威力的数据文档教程知识库上一篇Fluid 开源项目使用教程下一篇【开源宝藏】Glow.nvim终端里的Markdown预览神器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表