flatMap

compactMapflatMap 的详细区别

虽然 compactMapflatMap 在某些场景下(例如处理可选值的数组)看似相似,但它们的设计目标和行为有本质上的区别。以下从概念、语法、功能差异以及使用场景来详细说明。


1. 定义与设计目标

flatMap

  • 定义
    • flatMap 是一个将 映射map)和 展平flatten)结合的操作。
    • 它会对数组中的每个元素应用一个闭包操作,并将返回的结果「拍平」(如果结果是嵌套的数组)。
  • 设计目标
    • 用于将数组的每个元素映射到新值,同时展平嵌套的数组或去除可选值中的 nil
    • 适用于嵌套数组(如 [[1, 2], [3, 4]])的展开操作。

compactMap

  • 定义
    • compactMap 是专门用于处理 可选值的数组 的操作。
    • 它会对数组的每个元素应用一个闭包操作,将结果中的 nil 值过滤掉,最终返回一个非可选值的数组。
  • 设计目标
    • 用于过滤掉映射操作结果中的 nil 值。
    • 不适用于嵌套数组展开。

2. 核心区别

特性flatMapcompactMap
作用范围同时支持嵌套数组展平和过滤 nil专注于过滤 nil
嵌套数组展开会展开嵌套数组不会展开嵌套数组
处理 nil能过滤 nil,但设计初衷并非专注于此专门用于过滤 nil 的场景
结果结构单层展平后的新数组nil 值的新数组

3. 行为示例

flatMap 示例

3.1 嵌套数组的展开

swift

CopyEdit

let nestedArray = [[1, 2], [3, 4], [5]] let flattenedArray = nestedArray.flatMap { $0 } print(flattenedArray) // 输出:[1, 2, 3, 4, 5]

  • 解释flatMap 对每个子数组直接取值,并展平嵌套结构。

3.2 过滤 nil 的可选值数组

swift

CopyEdit

let optionalArray: [Int?] = [1, nil, 3, nil, 5] let result = optionalArray.flatMap { $0 } print(result) // 输出:[1, 3, 5]

  • 解释flatMap 会对每个元素解包,如果是 nil 则会被丢弃。

compactMap 示例

3.3 处理可选值数组

swift

CopyEdit

let optionalArray: [Int?] = [1, nil, 3, nil, 5] let result = optionalArray.compactMap { $0 } print(result) // 输出:[1, 3, 5]

  • 解释compactMap 专门用于过滤掉 nil 值,返回非可选值数组。

3.4 不展开嵌套数组

swift

CopyEdit

let nestedArray = [[1, 2], nil, [3, 4]] let result = nestedArray.compactMap { $0 } print(result) // 输出:[[1, 2], [3, 4]]

  • 解释compactMap 不会展平嵌套结构,仅对数组中的元素过滤掉 nil

4. 什么时候用 flatMapcompactMap

使用 flatMap 的场景

  1. 嵌套数组需要展平

    • 例如将二维数组转为一维数组。

    swift

    CopyEdit

    let nestedArray = [[1, 2], [3, 4]] let flattenedArray = nestedArray.flatMap { $0 } print(flattenedArray) // [1, 2, 3, 4]

  2. 同时映射和展平操作

    • 当映射的结果本身是数组,并希望展开成一维数组。

    swift

    CopyEdit

    let strings = ["apple", "banana"] let characters = strings.flatMap { $0.map { String($0) } } print(characters) // ["a", "p", "p", "l", "e", "b", "a", "n", "a", "n", "a"]


使用 compactMap 的场景

  1. 过滤 nil

    • 当数据中包含可选值,需要去除所有 nil 并保留非空值。

    swift

    CopyEdit

    let optionalNumbers: [Int?] = [1, nil, 3, nil, 5] let nonNilNumbers = optionalNumbers.compactMap { $0 } print(nonNilNumbers) // [1, 3, 5]

  2. 映射并过滤结果为 nil 的数据

    • 如果闭包操作可能返回 nil,可以用 compactMap 过滤掉结果中的 nil

    swift

    CopyEdit

    let strings = ["1", "two", "3", "four"] let numbers = strings.compactMap { Int($0) } print(numbers) // [1, 3]


5. flatMap 在 Swift 5 的细化

在 Swift 5 中,flatMap 的功能被细化:

  • 对于嵌套数组的展开,仍然使用 flatMap
  • 对于处理可选值数组,推荐使用 compactMap

虽然 flatMap 仍然可以处理 nil 的过滤,但为了代码的可读性,compactMap 更加语义化。


6. 总结对比

特性flatMapcompactMap
核心功能映射 + 展平映射 + 过滤 nil
嵌套数组展开
过滤 nil支持(但非专注)
推荐用途嵌套结构展平处理可选值或映射过滤 nil 的场景

4o