23

flatMap について少し混乱しています (Swift 1.2 に追加)

オプションのタイプの配列があるとします。

let possibles:[Int?] = [nil, 1, 2, 3, nil, nil, 4, 5]

Swift 1.1 では、次のようなマップに続いてフィルターを実行します。

let filtermap = possibles.filter({ return $0 != nil }).map({ return $0! })
// filtermap = [1, 2, 3, 4, 5]

私はいくつかの方法で flatMap を使用してこれを実行しようとしました:

var flatmap1 = possibles.flatMap({
    return $0 == nil ? [] : [$0!]
})

var flatmap2:[Int] = possibles.flatMap({
    if let exercise = $0 { return [exercise] }
    return []
})

配列型を指定する必要があることを除いて、私は最後のアプローチを好みます (強制的なアンラップを行う必要がないため$0!... 私はこれらを恐れており、何としても避けています)。

コンテキストによってタイプを把握する代替手段はありますが、強制的なアンラップはありませんか?

4

5 に答える 5

39

Swift 4.1以降、compactMap を使用できます。

let possibles:[Int?] = [nil, 1, 2, 3, nil, nil, 4, 5]
let actuals = possibles.compactMap { $0 }

(Swift 4.1 では、flatMap の一部のオーバーロードが Compactmap に置き換えられました。これに関する詳細に興味がある場合は、例を参照してください: https://useyourloaf.com/blog/replacing-flatmap-with-compactmap/ )

Swift 2 b1 を使用すると、簡単に実行できます

let possibles:[Int?] = [nil, 1, 2, 3, nil, nil, 4, 5]
let actuals = possibles.flatMap { $0 }

以前のバージョンでは、次の拡張子を使用してこれをシムできます。

extension Array {
    func flatMap<U>(transform: Element -> U?) -> [U] {
        var result = [U]()
        result.reserveCapacity(self.count)
        for item in map(transform) {
            if let item = item {
                result.append(item)
            }
        }
        return result
    }
}

1 つの注意点 (Swift 2 にも当てはまります) は、変換の戻り値を明示的に入力する必要がある場合があることです。

let actuals = ["a", "1"].flatMap { str -> Int? in
    if let int = str.toInt() {
        return int
    } else {
        return nil
    }
}
assert(actuals == [1])

詳細については、http://airspeedvelocity.net/2015/07/23/changes-to-the-swift-standard-library-in-2-0-betas-2-5/を参照してください。

于 2015-07-24T17:14:55.293 に答える
0

これは私がかなり多くのことをしているように見えるので、これを行うための汎用関数を調査しています。

配列に拡張機能を追加しようとしたので、次のようなことpossibles.unwrapedができましたが、配列に拡張機能を作成する方法がわかりませんでした。代わりに、カスタム オペレータを使用しました。ここで最も難しいのは、選択するオペレータを見つけようとすることでした。最後に>!、配列がフィルタリングされ>てからアンラップされていることを示すことにしました!

let possibles:[Int?] = [nil, 1, 2, 3, nil, nil, 4, 5]

postfix operator >! {}

postfix func >! <T>(array: Array<T?>) -> Array<T> {
    return array.filter({ $0 != nil }).map({ $0! })
}

possibles>!
// [1, 2, 3, 4, 5]
于 2015-04-26T23:05:17.203 に答える
0

使用できますreduce

let flattened = possibles.reduce([Int]()) { 
        if let x = $1 { return $0 + [x] } else { return $0 } 
    }

あなたはまだタイプを宣言していますが、少し目立たなくなりました。

于 2015-04-25T20:43:42.200 に答える