如何在 Swift 中合并数组?完整解析与性能秘诀
如果你曾经用 Swift 写过代码,很可能遇到过这样的问题:“我有两个数组,如何将它们合并成一个?”这个问题看似简单,但背后却隐藏着优化和细节的整个世界。在 Stack Overflow 上,这个问题获得了数千次浏览——这并非偶然。今天,我们不仅会展示如何编写代码,还会深入编译器底层,了解当你写下 array1 + array2 时实际发生了什么。开始吧!
最直观的方法:+ 运算符
让我们从经典方法开始。在 Swift 中,数组可以像数字一样相加:
let first = [1, 2, 3]let second = [4, 5, 6]let result = first + secondprint(result) // [1, 2, 3, 4, 5, 6]很优雅,对吧?但并非总是很快。当你使用 + 时,Swift 会创建一个新数组,并将两个原始数组中的元素复制进去。如果你的数组很大(比如各有 10 万个元素),这对处理器来说是双倍的工作量。但等等——这里有一个叫做 copy-on-write (COW) 的细节。
Copy-on-Write 的魔法:Swift 如何节省内存
Swift 是一门聪明的语言。当你简单地将一个数组赋值给另一个数组时,它不会立即复制数据:
var a = [1, 2, 3]var b = a // 在数据被修改之前,a 和 b 指向同一块内存区域b.append(4) // 此时才发生真正的复制:b 获得自己的副本这被称为 copy-on-write。但在通过 + 合并时,这并不适用——结果始终是一个新数组。为什么?因为我们不仅仅是引用旧数据,而是从两个不同来源的元素创建一个新的集合。编译器无法保证原始数组不会被修改,因此它会进行完整复制。
append(contentsOf:) 方法:当速度更重要时
如果你需要将一个数组的元素添加到另一个数组的末尾,而不创建第三个数组,请使用 append(contentsOf:):
var numbers = [1, 2, 3]let moreNumbers = [4, 5, 6]numbers.append(contentsOf: moreNumbers)print(numbers) // [1, 2, 3, 4, 5, 6]在这种情况下,Swift 不会创建新数组——它只是扩展现有数组。如果 numbers 数组有足够的预留内存(capacity),新元素会直接复制到空闲位置。如果没有,则会进行内存重新分配,但这仍然比从头创建数组要快。
专业建议: 如果你知道将要添加大量元素,请使用 reserveCapacity() 预先分配内存:
var bigArray: [Int] = []bigArray.reserveCapacity(1000)for i in 0..<1000 { bigArray.append(i) // 没有一次多余的复制!}flatMap 方法:带转换的数组合并
有时你不仅需要连接数组,还需要对每个元素进行转换。这时 flatMap(或用于可选值的 compactMap)就派上用场了。严格来说,flatMap 用于“展平”集合,但也可以用于拼接:
let arrays = [[1, 2], [3, 4], [5, 6]]let flattened = arrays.flatMap { $0 }print(flattened) // [1, 2, 3, 4, 5, 6]在底层,flatMap 做的事情与使用 append(contentsOf:) 的循环相同。但代码更简洁、更易读。不过,如果你只是要连接两个数组——不要使用 flatMap,那样会显得冗余。
使用 reduce(into:) 进行灵活合并
如果你有一个数组的数组,并且希望以额外的逻辑合并它们,可以尝试 reduce(into:):
let arrayOfArrays = [[1, 2], [3, 4], [5, 6]]let merged = arrayOfArrays.reduce(into: [Int]()) { r