文章目录

Swift 函数式编程:map、filter、reduce

发布于 2026-04-10 17:20:26 · 浏览 6 次 · 评论 0 条

Swift 函数式编程:map、filter、reduce

Swift 中的高阶函数(Higher-Order Functions)能够让你用更简洁、更声明式的方式处理集合数据(如数组、字典)。相比传统的 for 循环,使用 mapfilterreduce 可以大幅减少代码量,并提升代码的可读性。

本文将带你通过实战步骤掌握这三个核心函数。


1. 使用 map 进行数据转换

map 的核心作用是遍历集合并对每个元素执行相同的操作,最后返回一个包含新元素的新数组。

场景模拟

假设你有一个存储商品价格的数组,所有价格都是整数(单位:元)。你需要将它们转换为字符串,并在后面加上货币符号 "¥"。

操作步骤

  1. 创建 一个包含整数的数组。
  2. 调用 数组的 map 方法。
  3. 编写 闭包逻辑,将传入的整数 `$0` 转换为字符串并拼接符号。 ```swift let prices = [100, 200, 150, 80] let formattedPrices = prices.map { price in return "¥\(price)" } // 或者使用简写参数名 $0
    let shortFormattedPrices = prices.map { "¥($0)" } ``` 执行后,`formattedPrices` 的结果为 `["¥100", "¥200", "¥150", "¥80"]`。 **注意**:原数组 `prices` 的内容不会改变,`map` 总是返回一个新的数组。 --- ## 2. 使用 filter 筛选数据 `filter` 的核心作用是**遍历**集合并筛选出符合条件的元素,返回一个只包含符合条件元素的新数组。 ### 场景模拟 继续使用上面的价格数组。你需要筛选出所有价格大于 100 的商品。 ### 操作步骤 1. **确认** 筛选条件(例如:价格 > 100)。 2. **调用** 数组的 `filter` 方法。 3. **编写** 闭包逻辑,返回 `true` 表示保留该元素,返回 `false` 表示丢弃。 ```swift let prices = [100, 200, 150, 80] let expensivePrices = prices.filter { price in return price > 100 } // 简写形式 let shortExpensivePrices = prices.filter { $0 > 100 }

执行后,expensivePrices 的结果为 [200, 150],100 和 80 因不满足条件被过滤掉了。


3. 使用 reduce 计算最终结果

reduce 是这三个函数中最灵活但也稍难理解的一个。它的作用是将数组中的所有元素合并成一个值。这个值可以是数字、字符串,甚至是数组。

核心逻辑

reduce 需要两个参数:

  1. 初始值:计算的起点(例如求和时通常是 0)。
  2. 闭包:定义如何将“当前的累积结果”和“新元素”进行合并。

公式逻辑可以理解为:
$$ 结果_{new} = 闭包(结果_{old}, 当前元素) $$

场景模拟

计算所有商品价格的总和。

操作步骤

  1. 设定 初始值为 0
  2. 调用 数组的 reduce 方法。
  3. 编写 闭包逻辑,$0` 代表当前的累积和,`$1 代表新读入的数字。
let prices = [100, 200, 150, 80]

let total = prices.reduce(0) { currentSum, price in
    return currentSum + price
}

// 简写形式:$0 为累积结果,$1 为当前元素
let shortTotal = prices.reduce(0, +)

执行后,total 的结果为 530


4. 综合实战:链式调用

在实际开发中,我们通常需要连续使用这三个函数。Swift 支持链式调用,让你可以像搭积木一样将操作串联起来。

场景模拟

假设你有一个包含商品名称和价格的数组。你需要完成以下需求:

  1. 取出所有商品的价格(map)。
  2. 筛选出价格大于 50 的商品(filter)。
  3. 计算这些满足条件商品的总价(reduce)。

操作步骤

  1. 定义 商品结构体 Product
  2. 创建 商品数组。
  3. 链式调用 map -> filter -> reduce
// 定义商品结构体
struct Product {
    let name: String
    let price: Int
}

let products = [
    Product(name: "Apple", price: 10),
    Product(name: "Banana", price: 20),
    Product(name: "Steak", price: 100),
    Product(name: "Wine", price: 80)
]

let totalCost = products
    // 步骤 1: 映射:将 [Product] 转换为 [Int] (只取价格)
    .map { $0.price }
    // 步骤 2: 过滤:只保留价格 > 50 的项
    .filter { $0 > 50 }
    // 步骤 3: 归约:从 0 开始,将剩下的价格加起来
    .reduce(0, +)

执行后,totalCost 的计算过程如下:

  1. map 后得到 [10, 20, 100, 80]
  2. filter 后得到 [100, 80]
  3. reduce 计算结果为 180

传统循环 vs 函数式对比

为了直观展示差异,以下是实现相同逻辑的传统 for 循环写法:

var totalCostTraditional = 0
for product in products {
    let price = product.price
    if price > 50 {
        totalCostTraditional += price
    }
}

虽然两种写法结果一致,但函数式链式调用将“做什么”(取值、筛选、求和)清晰地分离开来,而 for 循环则混杂了“怎么做”的细节。在处理复杂数据流时,函数式编程能显著降低维护成本。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文