告别重复代码:SwifterSwift的Array/Dictionary等20个集合扩展技巧完整清单
【免费下载链接】SwifterSwiftA handy collection of more than 500 native Swift extensions to boost your productivity.项目地址: https://gitcode.com/gh_mirrors/sw/SwifterSwift
SwifterSwift 是一款包含 500+ 原生 Swift 扩展的开源工具库,专为 iOS、macOS、Linux 等平台的开发者提速而来。对于每天都要和Array、Dictionary、Sequence打交道的你来说,它内置的集合扩展技巧堪称刚需——去重、分组、安全交换、负数下标……这些曾经要自己写一堆样板代码才能实现的功能,现在一行调用就能搞定。本文整理了其中最实用的20 个 Array/Dictionary 等集合扩展技巧,帮你彻底告别重复代码 🚀
一分钟上手:安装 SwifterSwift
集合扩展属于SwiftStdlib子模块,三种安装方式任选其一:
- CocoaPods:在
Podfile中写pod 'SwifterSwift'(或仅引入pod 'SwifterSwift/SwiftStdlib') - Carthage:
Cartfile中添加github "SwifterSwift/SwifterSwift" ~> 6.0 - Swift Package Manager:在依赖里添加 SwifterSwift 包(
from: "6.0.0")
安装要求 Swift 5.6+,支持 iOS 12 / tvOS 12 / macOS 10.13 / Ubuntu 14.04+,详见 README.md。
💡 技巧速查时可直接翻源码:集合类扩展全部位于
Sources/SwifterSwiftSwiftStdlib/目录,一个类型一个文件,结构非常清晰。
Array 数组扩展:去重、安全交换一次搞定(8 招)
数组是日常使用频率最高的集合类型,ArrayExtensions.swift 提供了大量"少写几行循环"的实用方法。
1.prepend:在数组头部插入元素
往数组最前面加元素,不用再手动insert(_:at: 0):
var arr = [2, 3, 4] arr.prepend(1) // -> [1, 2, 3, 4]见 ArrayExtensions.swift#L31-L33
2.safeSwap:安全交换两个位置的元素
传统swapAt下标越界会直接崩溃,而safeSwap越界时静默跳过,处理用户输入的排序/拖拽场景更稳:
[1, 2, 3, 4, 5].safeSwap(from: 3, to: 0) // -> [4, 2, 3, 1, 5] [1, 2].safeSwap(from: 10, to: 0) // 越界,不崩溃,原样返回见 ArrayExtensions.swift#L43-L48
3.removeAll:删除所有指定元素
一次性删除数组中所有等于目标值的元素(也支持传入一组值批量删):
[1, 2, 2, 3, 4, 5].removeAll(2) // -> [1, 3, 4, 5] [1, 2, 2, 3, 4, 5].removeAll([2, 5]) // -> [1, 3, 4]见 ArrayExtensions.swift#L81-L98
4.removeDuplicates:原地去重
保留首次出现的元素,直接修改原数组:
var list = [1, 2, 2, 3, 4, 5] list.removeDuplicates() // -> [1, 2, 3, 4, 5]5.withoutDuplicates:不可变去重
不想改动原数组?这个版本返回新数组,函数式风格更友好:
["h", "e", "l", "l", "o"].withoutDuplicates() // -> ["h", "e", "l", "o"]见 ArrayExtensions.swift#L124-L131
6.withoutDuplicates(keyPath:):按属性去重
处理模型对象数组时非常实用——按某个属性(如id)去重,告别手动维护Set记录:
let unique = users.withoutDuplicates(keyPath: \.id)7.sorted(like:keyPath:):参照另一数组排序
想让当前数组按另一个数组定义的顺序排列(比如按"用户收藏顺序"展示商品),这个方法可以替代手写排序逻辑。未出现在参照数组中的元素排到最后。
8.init(count:element:):按索引批量初始化
let squares = Array(count: 5) { $0 * $0 } // -> [0, 1, 4, 9, 16]见 ArrayExtensions.swift#L12-L19
Dictionary 字典扩展:四招让数据处理更优雅
DictionaryExtensions.swift 补齐了字典操作中最常见的痛点。
9.has(key:):优雅地检查键是否存在
替代dict[key] == nil这种"看起来不靠谱"的写法,语义一目了然:
dict.has(key: "testKey") // -> true见 DictionaryExtensions.swift#L27-L29
10.removeAll(keys:):按键批量删除
var dict = ["key1": "v1", "key2": "v2", "key3": "v3"] dict.removeAll(keys: ["key1", "key2"]) // 只剩 key311.removeValueForRandomKey:随机移除一项
抽奖、洗牌、随机剔除场景一行代码解决:
var pool = ["A", "B", "C"] pool.randomKeys.forEach { _ in pool.removeValueForRandomKey() }12.jsonString:字典一行转 JSON 字符串
调试时打印字典、接口拼参特别顺手,还支持prettify: true输出格式化结果:
dict.jsonString(prettify: true)见 DictionaryExtensions.swift#L90-L96
补充:
init(grouping:by:)还接受 KeyPath 版本,Dictionary(grouping: students, by: \.className)一行完成"按班级分组"。
Sequence 序列扩展:过滤与遍历的语法糖(4 招)
SequenceExtensions.swift 对所有序列类型生效(Array、Set、字典的 values……),是最通用的"瑞士军刀"。
13.all / none / any(matching:):条件判断三件套
[2, 2, 4].all(matching: { $0 % 2 == 0 }) // -> true [1, 3, 5].none(matching: { $0 % 2 == 0 }) // -> true [2, 3, 4].any(matching: { $0 > 3 }) // -> true见 SequenceExtensions.swift#L11-L35
14.reject(where:):反向 filter
filter是"留下满足条件的",reject则是"留下不满足条件的"——当你不想写!条件时非常舒服:
[2, 2, 4, 7].reject(where: { $0 % 2 == 0 }) // -> [7]15.forEachReversed:从后往前遍历
[0, 2, 4, 7].forEachReversed { print($0) } // 打印顺序:7, 4, 2, 016.accumulate:返回累加过程的每一步
标准reduce只给最终结果,accumulate会把中间过程也返回,适合做走势图、累计统计:
[1, 2, 3].accumulate(initial: 0, next: +) // -> [1, 3, 6]见 SequenceExtensions.swift#L75-L80
Collection 集合扩展:分组、定位一步到位(3 招)
CollectionExtensions.swift 覆盖所有 Collection 类型。
17.group(by:):按大小分块
把长列表切成固定长度的小块(分页加载、批量请求必备):
[1, 2, 3, 4, 5].group(by: 2) // -> [[1, 2], [3, 4], [5]]18.indices(where:):找出所有满足条件的下标
不用自己enumerate+append,直接拿符合条件的全部索引:
let idx = [10, 20, 30].indices(where: { $0 > 15 }) // -> [1, 2]19.indices(of:):找出某元素的所有位置
元素在数组中出现多次时,firstIndex(of:)只能给一个,indices(of:)全部给你:
[1, 2, 2, 3].indices(of: 2) // -> [1, 2]📌 同文件中还有
adjacentPairs()(生成相邻元素对,做差分/滑窗很方便)和forEach(slice:)(按切片回调),也值得一试。
MutableCollection 等扩展:KeyPath 排序与负数下标(3 招)
20.sort(by:):一行按属性排序(支持多级排序)
MutableCollectionExtensions.swift 让按 KeyPath 排序变得极其简洁,还支持按两个、三个 KeyPath依次比较(比如先按班级、再按分数):
users.sort(by: \.age) users.sort(by: \.score, and: \.name)同文件的assignToAll(value:by:)可把某个值批量赋给所有元素的属性,例如"一键清空所有任务的完成标记"。
21.subscript(offset:):支持负数的下标
BidirectionalCollectionExtensions.swift 带来"Python 式"的下标体验——-1就是最后一个元素:
let arr = [1, 2, 3, 4, 5] arr[offset: 1] // -> 2 arr[offset: -2] // -> 4见 BidirectionalCollectionExtensions.swift#L14-L17
附赠:RangeReplaceableCollection全家桶
RangeReplaceableCollectionExtensions.swift 还藏着一组高频方法:take(while:)(取前段)、skip(while:)(跳前段)、keep(while:)(留前段)、removeFirst(where:)(删第一个满足条件的)、removeRandomElement()(随机删一个)……配合前面的技巧,基本可以覆盖 90% 的日常集合操作。
总结:这套清单能帮你省多少事?
| 场景 | 传统写法 | SwifterSwift 一招 |
|---|---|---|
| 数组去重 | 手写 reduce + Set | withoutDuplicates() |
| 批量删元素 | 手写循环 | removeAll([2, 5]) |
| 安全交换 | guard 判断下标 | safeSwap(from:to:) |
| 字典转 JSON | 三步 JSONSerialization | jsonString(prettify:) |
| 按属性排序 | 手写比较闭包 | sort(by: \.age) |
| 取倒数第 2 个 | arr[count-2]还要判空 | arr[offset: -2] |
这些扩展全部原生 Swift 实现、无第三方依赖,通过 CocoaPods / Carthage / SPM 引入即可开箱即用(包定义见 Package.swift 与 SwifterSwift.podspec)。配合仓库内置的 Examples/Examples.playground 游乐场,你可以边跑边学。与其继续复制粘贴自己写的"轮子",不如把这个 500+ 扩展的清单加进你的工具箱——从今天的第一行prepend开始 ✨
【免费下载链接】SwifterSwiftA handy collection of more than 500 native Swift extensions to boost your productivity.项目地址: https://gitcode.com/gh_mirrors/sw/SwifterSwift
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考