Swift学习——map和flatMap

记录一下Swift中的map和flatMap。git

网上不少文章都是以前的,那时flatMap的定义还有两个重载的函数,对应的源码也是以前版本的~所以我在没看源码前,对flatMap的实现有了一些误解。由下面这段代码的输出引起的本次探索。github

let arr = [1, 2, 3]

print(arr.map{"NO.\($0)"})
print(arr.flatMap{"NO.\($0)"})
复制代码

数组支持的map和flatMap实现

map

先贴源码swift

@inlinable
  public func map<T>(
    _ transform: (Element) throws -> T
  ) rethrows -> [T] {
    let initialCapacity = underestimatedCount
    var result = ContiguousArray<T>()
    result.reserveCapacity(initialCapacity)

    var iterator = self.makeIterator()

    // Add elements up to the initial capacity without checking for regrowth.
    for _ in 0..<initialCapacity {
      result.append(try transform(iterator.next()!))
    }
    // Add remaining elements, if any.
    while let element = iterator.next() {
      result.append(try transform(element))
    }
    return Array(result)
  }
复制代码

这段源码和网上大多文章同样,map里面的处理以下。api

  1. 建立一个新的数组
  2. 遍历数组处理闭包函数,并将结果添加到数组中
  3. 返回该数组

flatMap

结合咱们从Xcode中看到的解释以及源码,咱们能够知道flatMap就是返回的Array(s.map(transform).joined())数组

public func flatMap<SegmentOfResult>(
    _ transform: @escaping (Elements.Element) -> SegmentOfResult
  ) -> LazySequence<
    FlattenSequence<LazyMapSequence<Elements, SegmentOfResult>>> {
    return self.map(transform).joined()  
  }
复制代码

因此,以前的实现方法appendContents那种都无效了。所以开头那个demo输出也和以前不同了(按以前的实现,flatMap输出的和map同样),结果以下。bash

["NO.1", "NO.2", "NO.3"]
["N", "O", ".", "1", "N", "O", ".", "2", "N", "O", ".", "3"]
复制代码

用flatMap的时候,结果返回有可选值的时候,好比对数组里面的字符串转成Int,Xcode会提示咱们用compactMap方法。 闭包

Optional支持的map和flatMap实现

我是看的唐巧大神的文章Swift 烧脑体操(四) - map 和 flatMapapp

本身也整理了一下。 源码地址函数

@inlinable
  public func map<U>(
    _ transform: (Wrapped) throws -> U
  ) rethrows -> U? {
    switch self {
    case .some(let y):
      return .some(try transform(y))
    case .none:
      return .none
    }
  }
  
@inlinable
  public func flatMap<U>(
    _ transform: (Wrapped) throws -> U?
  ) rethrows -> U? {
    switch self {
    case .some(let y):
      return try transform(y)
    case .none:
      return .none
    }
  }
复制代码

这段代码,乍一看相同,不一样之处在于:ui

  1. flatMap的tranform返回的是U?,调用的结果return try transform(y)
  2. map返回的是U,调用的结果return .some(try transform(y))

因此map有可能形成多重Optional的问题,Optional嵌套可看唐巧大神的文章 https://blog.devtang.com/2016/02/27/swift-gym-1-nested-optional/

相关文章
相关标签/搜索