0%

map和flapMap的一点区别

Array中的map和flapMap的一点区别

注意:map和flapMap方法在很多类型里都有定义,一定要看清楚方法声明。

map的声明:

1
@inlinable public func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]

它返回的是一个数组.闭包的返回值是一个新数组的元素. 默认情况下,只要闭包有可能返回一个optional类型元素,则map返回的将是一个[T?]数组.

flapMap的声明: 有两种声明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@available(swift, deprecated: 4.1, renamed: "compactMap(_:)", message: "Please use compactMap(_:) for the case where closure returns an optional value")
public func flatMap<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]

/// Returns an array containing the concatenated results of calling the
/// given transformation with each element of this sequence.
///
/// Use this method to receive a single-level collection when your
/// transformation produces a sequence or collection for each element.
///
/// In this example, note the difference in the result of using `map` and
/// `flatMap` with a transformation that returns an array.
///
/// let numbers = [1, 2, 3, 4]
///
/// let mapped = numbers.map { Array(repeating: $0, count: $0) }
/// // [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4]]
///
/// let flatMapped = numbers.flatMap { Array(repeating: $0, count: $0) }
/// // [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
///
/// In fact, `s.flatMap(transform)` is equivalent to
/// `Array(s.map(transform).joined())`.
///
/// - Parameter transform: A closure that accepts an element of this
/// sequence as its argument and returns a sequence or collection.
/// - Returns: The resulting flattened array.
///
/// - Complexity: O(*m* + *n*), where *n* is the length of this sequence
/// and *m* is the length of the result.
@inlinable public func flatMap<SegmentOfResult>(_ transform: (Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Element] where SegmentOfResult : Sequence

@inlinable public func compactMap<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]

二者区别:

  1. flatMap可以用来展平一个数组:它把原序列里的元素变为一个序列,然后把这个序列的元素添加到结果序列中,相当于降维了。展的有多平得看transform的实现,不过最少是减一层。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    let links: [[String]] = [
    ["http://a1", "http://a2", "http://a3"],
    ["http://b1", "http://b2", "http://b3"],
    ["http://c1", "http://c2", "http://c3"],
    ]
    print(links)

    let flapLink = links.flatMap { (exlinks: [String]) -> [String] in
    return exlinks //因为links的元素就是数组所以这里直接返回就可以了。
    }
    print(flapLink) //["http://a1", "http://a2", "http://a3", "http://b1", "http://b2", "http://b3", "http://c1", "http://c2", "http://c3"]

    let d3: [[[Int]]] = [
    [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
    [[10, 11, 12], [13, 14, 15], [16, 17, 18]],
    [[19, 20, 21], [22, 23, 24], [25, 26, 27]],
    ]
    //[[Int]]
    let flapD1 = d3.flatMap { ele in
    return ele
    }
    //[Int]
    let flapD2 = d3.flatMap { ele in
    return ele.flatMap{$0}
    }

    let colors = ["♥", "♠", "♦", "♣"]
    let numbers = ["J", "Q", "K", "A"]
    let cards = colors.flatMap { color in
    return numbers.map { num in
    return "\(color)-\(num)"
    }
    }
    print(cards) //["♥-J", "♥-Q", "♥-K", "♥-A", "♠-J", "♠-Q", "♠-K", "♠-A", "♦-J", "♦-Q", "♦-K", "♦-A", "♣-J", "♣-Q", "♣-K", "♣-A"]
  2. flatMap可以将转化失败的nil元素剔除,而map则不能:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    let wq = ["123", "fsd", "dfsd", "34"]
    //类型是[Int?]
    let wqm = wq.map { (element) -> Int? in
    return Int(element)
    }
    print(wqm) //[Optional(123), nil, nil, Optional(34)]

    //类型是[Int]
    let wqfm = wq.flatMap { (element) -> Int? in
    return Int(element)
    }
    print(wqfm) //[123, 34]

由于剔除nil元素的用法已经被废弃,Apple推荐使用compactMap代替,因此flatMap的用法主要是第一种了.

Optional枚举类型中的map和flatMap

map:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/// Evaluates the given closure when this `Optional` instance is not `nil`,
/// passing the unwrapped value as a parameter.
///
/// Use the `map` method with a closure that returns a non-optional value.
/// This example performs an arithmetic operation on an
/// optional integer.
///
/// let possibleNumber: Int? = Int("42")
/// let possibleSquare = possibleNumber.map { $0 * $0 }
/// print(possibleSquare)
/// // Prints "Optional(1764)"
///
/// let noNumber: Int? = nil
/// let noSquare = noNumber.map { $0 * $0 }
/// print(noSquare)
/// // Prints "nil"
///
/// - Parameter transform: A closure that takes the unwrapped value
/// of the instance.
/// - Returns: The result of the given closure. If this instance is `nil`,
/// returns `nil`.
@inlinable public func map<U>(_ transform: (Wrapped) throws -> U) rethrows -> U?

flatMap:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/// Evaluates the given closure when this `Optional` instance is not `nil`,
/// passing the unwrapped value as a parameter.
///
/// Use the `flatMap` method with a closure that returns an optional value.
/// This example performs an arithmetic operation with an optional result on
/// an optional integer.
///
/// let possibleNumber: Int? = Int("42")
/// let nonOverflowingSquare = possibleNumber.flatMap { x -> Int? in
/// let (result, overflowed) = x.multipliedReportingOverflow(by: x)
/// return overflowed ? nil : result
/// }
/// print(nonOverflowingSquare)
/// // Prints "Optional(1764)"
///
/// - Parameter transform: A closure that takes the unwrapped value
/// of the instance.
/// - Returns: The result of the given closure. If this instance is `nil`,
/// returns `nil`.
@inlinable public func flatMap<U>(_ transform: (Wrapped) throws -> U?) rethrows -> U?

上面两个区别仅是闭包参数的返回值不同。不仔细看还真发现不了。如果transform的结果可能为nil则需要使用flatMap。如果不可能为nil则可以使用map。

觉得文章有帮助可以打赏一下哦!