首页 / Swift 编程语言教程 / 集合高阶操作

Swift 编程语言教程

集合高阶操作

本教程共 93 篇 · 第 20 篇 · 更新于 2026-08-08 · 约 8 分钟阅读

SwiftSwift 编程语言教程mapfilterreducesorted高阶函数集合操作

本节目标:读完你能用 map、filter、reduce、sorted 等函数处理数组等集合,写出比传统循环更短更清晰的代码。

前面遍历集合都用 for-in 手动处理。Swift 还提供一组”高阶函数”:它们接收一个”操作”作为参数,对集合每个元素套用。这类写法更短、更声明式,是 Swift 处理数据的利器。这一章挑最常用的几个讲。

1-1 什么是高阶函数

高阶函数是指”把函数(或闭包)当参数”的函数。集合上的 map、filter、reduce 都是典型:你告诉它”对每个元素做什么”,它替你跑完整个集合并把结果整理好。

这里的”函数参数”在 Swift 里常以闭包形式写出。闭包的细节后面有专门章节,本章你只需看懂它的样子。

1-2 map:把每个元素变一变

map 对集合每个元素施加同一个转换,返回一个”转换后”的新集合,长度不变。

let numbers = [1, 2, 3, 4]
let doubled = numbers.map { $0 * 2 }
// [2, 4, 6, 8]

{ $0 * 2 } 是个闭包,$0 代表”当前元素”。整句意思是:把每个数乘以 2,得到新数组。map 不改原数组,而是产出新数组。

map 还能改变元素类型,比如把数字数组变成字符串数组:

let strings = numbers.map { "数 \($0)" }
// ["数 1", "数 2", "数 3", "数 4"]

1-3 filter:按条件筛出

filter 保留满足条件的元素,返回一个”过滤后”的新集合(长度可能变短)。

let evens = numbers.filter { $0 % 2 == 0 }
// [2, 4]

闭包里返回 true 的元素被留下,false 的被丢弃。想筛”大于 2 的数""名字以某字母开头”,都是 filter 的活。

1-4 reduce:把全部元素压成一个值

reduce 把集合”折叠”成单个值,比如求和、拼接。它接收两个东西:初始值,和”如何把当前结果和下一个元素合并”的闭包。

let sum = numbers.reduce(0) { $0 + $1 }
// 0 + 1 + 2 + 3 + 4 = 10

reduce(0)0 是累加起点,$0 是”目前累计值”、$1 是”当前元素”。每一步把两者相加,最终得到总和 10。

拼接字符串也常用 reduce:

let words = ["Swift", "很", "好玩"]
let sentence = words.reduce("") { $0 + $1 }
// "Swift很好玩"

1-5 sorted:排序

sorted() 返回排好序的新数组,不改动原数组。默认按升序:

let unordered = [3, 1, 4, 1, 5]
let ordered = unordered.sorted()
// [1, 1, 3, 4, 5]

要自定义排序规则,传一个”比较两个元素”的闭包。比如降序:

let descending = unordered.sorted { $0 > $1 }
// [5, 4, 3, 1, 1]

注意 sorted() 返回新数组;如果想原地排序可变数组,用 sort()(无返回值)。字符串等也能 sorted(),按字符顺序排。

1-6 链式组合

这些函数返回的还是集合,所以可以串起来用。比如”先筛偶数,再各自乘 2,最后求和”:

let result = numbers
    .filter { $0 % 2 == 0 }
    .map { $0 * 2 }
    .reduce(0) { $0 + $1 }
// (2,4) -> (4,8) -> 12

链式写法把”数据流水线”表达得很清楚:每一步的输入是上一步的输出。比起嵌套循环,这种代码更像在描述”我要什么”,而不是”怎么一步步做”。

1-7 forEach:遍历但不产出

forEach 对每个元素执行一段操作,类似 for-in,但它是方法调用:

numbers.forEach { print($0) }

它不返回新集合,仅用于”挨个做副作用”(如打印、记录)。需要产出新集合时,别用 forEach,用 map 等。

1-8 可变性要分清

高阶函数大多返回新集合,不动原集合。比如 sorted() 返回新的,map/filter/reduce 也都是产出新的。这与”值类型”的作风一致:原数据默认不改。

如果你想把结果存回原变量,重新赋值即可:

var list = [3, 1, 2]
list = list.sorted()   // list 现在是 [1, 2, 3]

只有 sort()(无 ed)、append 这类”原地”方法会直接修改 var 变量。看清”返回新值”还是”原地修改”,是避免 bug 的关键。

Tip

新手常纠结 $0$1 是什么:它们是闭包参数的简写占位,$0 是第一个参数(当前元素),$1 是第二个(如累计值)。初学看不惯就先写成完整 { element in ... } 形式,熟悉后再用简写。

1-9 性能与可读性

高阶函数底层仍是遍历,性能上和手写循环差不多,但可读性和表达力往往更高。当逻辑清晰、数据量不大时,优先用它们让代码更短更直白。

不过链式太长、闭包太复杂时,也会变难读。那时的解法是拆成有意义的步骤或变量,而非硬塞进一行。可读性永远第一。

1-10 高阶函数的使用分寸

高阶函数是 Swift 处理集合的优雅武器,理解它们能让你写出比循环更短更清晰的代码。map 转换每个元素(保长)、filter 按条件筛选、reduce 折叠成单值、sorted 返回排序新数组、forEach 仅遍历。它们接收闭包作参数,可链式组合成数据流水线。

大部分高阶函数返回新集合、不改原数据,这和”值类型”作风一致:原数据默认不动。想要结果存回原变量就重新赋值;只有 sort()(无 ed)、append 这类”原地”方法才直接修改 var。看清”返回新值”还是”原地修改”,是避免 bug 的关键。

闭包里的 $0$1 是参数简写占位($0 当前元素,$1 累计值)。初看不惯就先写成完整 { element in ... },熟悉后再用简写。链式写法把”数据流水线”表达得很清楚,但太长太复杂也会变难读,那时拆成有意义的步骤或变量,可读性第一。

forEachfor-in 类似但它是方法调用,不返回新集合,仅用于做副作用(打印、记录)。需要产出新集合时用 map 等,别用 forEach。性能上高阶函数和手写循环差不多,但可读性和表达力往往更高,数据量不大时优先用它们。

到这里模块二”基础语法”收尾。你已掌握变量常量、类型推断、基础类型、字符串、元组、运算符、三种集合及其高阶操作。下一模块进入流程控制——用 ifswitch、循环决定程序走哪条路。闭包是高阶函数的灵魂,本章只让你见过样子,后面有专门章节系统讲它的语法与简写,到时候 $0 这类写法你会彻底通透。把高阶函数当”描述你想要什么”而非”指挥怎么一步步做”,你的集合代码会清爽很多。

1-11 小结与模块收尾

map 转换每个元素(保长)、filter 按条件筛选、reduce 折叠成单值、sorted 返回排序新数组、forEach 仅遍历。它们接收闭包作参数,可链式组合成数据流水线,且大多返回新集合、不改原数据。

到这里,模块二”基础语法”告一段落:你已掌握变量常量、类型推断、基础类型、字符串、元组、运算符、以及三种集合及其高阶操作。下一模块我们将进入流程控制——用 if、switch、循环决定程序”走哪条路”。

Note

闭包是高阶函数的灵魂,本章只让你见过它的样子。后面会有专门章节系统讲闭包语法与简写,到时候 $0 这类写法你会彻底通透。