Skip item when performing map in Swift?

2019-02-13 06:46发布

I'm applying a map to a dictionary that has a try in it. I'd like to skip the iteration if the mapped item is invalid.

For example:

func doSomething<T: MyType>() -> [T]
    dictionaries.map({
        try? anotherFunc($0) // Want to keep non-optionals in array, how to skip?
    })
}

In the above sample, if anotherFunc returns nil, how to escape the current iteration and move on to the next? That way, it would not contain the items that are nil. Is this possible?

1条回答
Fickle 薄情
2楼-- · 2019-02-13 07:11

Just replace map() by flatMap():

extension SequenceType {
    /// Returns an `Array` containing the non-nil results of mapping
    /// `transform` over `self`.
    ///
    /// - Complexity: O(*M* + *N*), where *M* is the length of `self`
    ///   and *N* is the length of the result.
    @warn_unused_result
    public func flatMap<T>(@noescape transform: (Self.Generator.Element) throws -> T?) rethrows -> [T]
}

try? ... returns nil if the call throws an error, so those elements will be omitted in the result.

A self-contained example just for demonstration purposes:

enum MyError : ErrorType {
    case DivisionByZeroError
}

func inverse(x : Double) throws -> Double {
    guard x != 0 else {
        throw MyError.DivisionByZeroError
    }
    return 1.0/x
}

let values = [ 1.0, 2.0, 0.0, 4.0 ]
let result = values.flatMap {
    try? inverse($0)
}
print(result) // [1.0, 0.5, 0.25]

For Swift 3, replace ErrorType by Error.

For Swift 4 use compactMap

查看更多
登录 后发表回答