Swift-Algorithms 的基本使用

642 阅读4分钟

「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」。

Swift Algorithms 是 Swift 官方开源的一个框架,它主要提供一些作用于序列和集合的一些算法,以此来提高开发者的开发效率。

本文主要讲解以下几个内容:

  • 如何安装
  • 组合与排列
  • collection 的组合
  • 子序列的相关操作
  • 部分排序 废话不多说,下面让我们开始吧!

安装 Swift-Algorithms

点击 Xcode 的 File,选中菜单中的 Add Packages,在搜索框输入 Swift algorithms,点击底部的 add package 按钮即可安装。

安装完成之后,在需要使用的地方 import Algorithms。如果在导入之后报错:No such module,请按照下面的操作进行修复: Project Settings -> General -> My Target -> Frameworks, Libraries, and Embedded Content

点击下方 + 号,添加 Algorithms

组合与排列

获取集合元素的全排列 - combinations

假设,我们有一组数据,用来表示所有人的名字:

let names = ["伍六七", "鸡大保", "梅花十一", "梅花十三"]

我们接到一个需求,需要得到数组中的所有元素可以组出多少组的 CP,代码如下:

for cp in names.combinations(ofCount: 2) {
    print(cp)
}

// 所有的 CP 组合
//["伍六七", "鸡大保"]
//["伍六七", "梅花十一"]
//["伍六七", "梅花十三"]
//["鸡大保", "梅花十一"]
//["鸡大保", "梅花十三"]
//["梅花十一", "梅花十三"]

需要注意的点:

  • 该函数的返回结果是有序的,按照元素的顺序返回排列。
  • 该函数不会进行去重操作。
let numbers2 = [20, 10, 10]
for combo in numbers2.combinations(ofCount: 2) {
    print(combo)
}
// 此处可以看到,[20, 10]出现两次。
// [20, 10]
// [20, 10]
// [10, 10]

更灵活的用法

combinations 不仅可以传递一个值,还可以传递一个范围。比如,我们可以统计 2 个元素和 3 个元素的全排列:

for result in names.combinations(ofCount: 2...3) {
    print(result)
}

// ["伍六七", "鸡大保"]
// ["伍六七", "梅花十一"]
// ["伍六七", "梅花十三"]
// ["鸡大保", "梅花十一"]
// ["鸡大保", "梅花十三"]
// ["梅花十一", "梅花十三"]
// ["伍六七", "鸡大保", "梅花十一"]
// ["伍六七", "鸡大保", "梅花十三"]
// ["伍六七", "梅花十一", "梅花十三"]
// ["鸡大保", "梅花十一", "梅花十三"]

collection 的组合

合并两个集合 - chain

如果不适用 Algorithm,我们会写下面的代码去访问两个集合中的元素:

let names1 = ["伍六七", "鸡大保", "梅花十一", "梅花十三"]
let names2 = ["青凤", "江主任"]

for name in names1 + names2 {
    print(name)
}

而有了 Algorithm 之后,我们可以用 chain 来优化下面的代码:

for name in chain(names1, names2) {
    print(name)
}

看到上面的代码,你可能会有一个疑惑:看起来就是把 + 换成了 chain 啊?

使用 chain 有下面两个好处:

  • 它只是存储集合的引用,不会去执行任何的 allocations 操作,而 + 实际上会创建一个临时变量。
  • chain 可以应用于任意的 sequence 类型,比如 range 和 Array:
let reservedSeats = 0...50
let unavailableSeats = [61, 68, 75, 76, 77, 92]
let disallowed = chain(reservedSeats, unavailableSeats)

let requestedSeat = 39
print(disallowed.contains(requestedSeat))

重复元素

通过 cycled 函数,可以进行集合元素的重复:

for name in names2.cycled(times: 2) {
    print(name)
}
//青凤
//江主任
//青凤
//江主任

cycled 函数的本质等同于 repeatElement(_:count:) + joined()

product

product 主要用于一个集合的每个元素去遍历访问另一个集合的元素。

比如,当前有两个集合:names 和 actions:

let actions = ["吃早餐", "吃午餐", "吃晚餐"]
let names = ["青凤", "江主任"]

我们每个人都需要每日吃三餐。所以,需要 names 中的每个元素去遍历 actions 的 action:

for (person, action) in product(names, actions) {
    print(person, action)
}

//青凤 吃早餐
//青凤 吃午餐
//青凤 吃晚餐
//江主任 吃早餐
//江主任 吃午餐
//江主任 吃晚餐

子序列的相关操作

同时获取最小值和最大值

使用 minAndMax,等同于 min + max:

let numbers = [7, 1, 6, 2, 8, 3, 9]
if let (smallest, largest) = numbers.minAndMax() {
	print(smallest, largest) // 1 9
}

去重

使用 uniqued() 进行集合去重:

let names = ["梅花十一", "青凤", "伍六七", "江主任", "伍六七", "鸡大保", "梅花十一"]
let unique = names.uniqued()
print(Array(unique)) // ["梅花十一", "青凤", "伍六七", "江主任", "鸡大保"

部分排序

使用 min(count:) 或者 max(count:) 来返回几个最大值或者最小值:

let numbers = [2, 4, 9, 5, 8]
print(numbers.min(count: 3)) // [2, 4, 5]

最后

本文只是对 Algorithm 框架的一个基本的介绍,其中还包括很多好玩的函数没有包含在本文中。十分推荐大家去看一下官方文档,去探索更多非常酷的功能。

参考链接