Tailwind CSSTailwind CSS
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
  • 第3章:函数式编程的基本技术

第3章:函数式编程的基本技术

3.1 映射、过滤与归约

在函数式编程(FP)中,映射(Map)、过滤(Filter)和归约(Reduce)是处理数据的三大基本技术。这些操作利用高阶函数,将集合的迭代抽象为简洁、声明式的表达式。它们不仅体现了函数式编程的核心思想,还广泛应用于实际开发中。本节将详细讲解它们的定义、用途和实现方式,并通过示例展示其强大之处。

映射(Map)的定义与用途

映射是一种操作,它将一个函数应用于集合中的每个元素,并返回一个新集合,新集合的每个元素是原始元素经过函数转换后的结果。映射的核心在于“变换”,而不改变原数据。

  • 定义:给定一个集合 S 和一个函数 f,map(f, S) 返回一个新集合,其中每个元素是 f 应用于 S 中对应元素的结果。
  • 用途:常用于数据转换,如将数字翻倍、字符串大写等。
# Python 示例:映射
numbers = [1, 2, 3, 4]
doubled = list(map(lambda x: x * 2, numbers))
print(doubled)  # 输出: [2, 4, 6, 8]

相比命令式循环,map 更简洁,且符合不可变性原则:

# 命令式对比
numbers = [1, 2, 3, 4]
doubled = []
for num in numbers:
    doubled.append(num * 2)

映射的优点在于,它将“如何迭代”交给语言或框架,开发者只需定义“做什么”。

过滤(Filter)的定义与用途

过滤是一种操作,它根据某个条件函数(谓词)筛选集合中的元素,返回一个新集合,仅包含满足条件的元素。过滤的核心在于“选择”。

  • 定义:给定一个集合 S 和一个谓词函数 p,filter(p, S) 返回一个新集合,仅包含 p 返回 True 的元素。
  • 用途:常用于数据筛选,如提取偶数、正数或特定条件的记录。
# Python 示例:过滤
numbers = [1, 2, 3, 4, 5]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)  # 输出: [2, 4]

与命令式代码相比,filter 避免了手动管理结果集合:

# 命令式对比
numbers = [1, 2, 3, 4, 5]
evens = []
for num in numbers:
    if num % 2 == 0:
        evens.append(num)

过滤操作天然支持组合,可以与其他函数式工具串联使用。

归约(Reduce)的定义与用途

归约(也称折叠,Fold)是一种操作,它通过一个二元函数将集合中的所有元素“归约”成单个值。归约的核心在于“聚合”。

  • 定义:给定一个集合 S、一个初始值 init 和一个二元函数 f,reduce(f, S, init) 从初始值开始,依次将 f 应用于当前结果和集合中的每个元素,最终返回单一值。
  • 用途:常用于求和、求积、连接字符串等聚合操作。
# Python 示例:归约
from functools import reduce
numbers = [1, 2, 3, 4]
total = reduce(lambda x, y: x + y, numbers)  # 默认初始值可选
print(total)  # 输出: 10

与命令式累加相比,reduce 更抽象:

# 命令式对比
numbers = [1, 2, 3, 4]
total = 0
for num in numbers:
    total += num

归约的灵活性在于,二元函数可以自定义。例如,求最大值:

max_val = reduce(lambda x, y: x if x > y else y, numbers)
print(max_val)  # 输出: 4

三者的组合应用

映射、过滤和归约可以无缝组合,形成强大的数据处理管道。例如,计算列表中正数的平方和:

numbers = [-2, -1, 0, 1, 2]
result = reduce(
    lambda x, y: x + y,              # 归约:求和
    map(lambda x: x * x,             # 映射:平方
        filter(lambda x: x > 0, numbers)  # 过滤:正数
    )
)
print(result)  # 输出: 5 (1² + 2² = 1 + 4)

这种管道式处理体现了函数式编程的声明式本质:每个步骤专注于单一职责,最终通过组合完成复杂任务。

在实践中的意义

  • 简洁性:三者消除了显式循环,使代码更紧凑。
  • 并行潜力:由于无副作用,map 和 filter 易于并行化,reduce 也可通过分治法优化。
  • 通用性:这些操作适用于任何集合类型(如列表、数组、流),在多种语言中都有类似实现(如 JavaScript 的 Array.map、Haskell 的 foldl)。

注意事项

  • 性能:在某些语言中(如 Python),map 和 filter 返回迭代器,需显式转换为列表,可能增加开销。
  • 可读性:过度嵌套(如上述管道示例)可能降低代码清晰度,建议为复杂逻辑命名函数。
  • 初始值:reduce 时若未提供初始值,可能会引发错误(如空集合),需谨慎处理。
# 安全的 reduce
empty = []
safe_sum = reduce(lambda x, y: x + y, empty, 0)  # 指定初始值 0
print(safe_sum)  # 输出: 0

小结

映射、过滤和归约是函数式编程中最基础且最强大的工具,它们通过高阶函数实现了数据的转换、筛选和聚合。掌握这些技术,不仅能提升代码的简洁性和可维护性,还为后续学习更高级的函数式概念(如 Monad)奠定了基础。下一节,我们将探讨“递归与尾递归优化”,进一步扩展函数式编程的控制流技术。

Last Updated:: 2/25/25, 10:59 AM