web-dev-qa-db-ja.com

SwiftのflatMapとcompactMapの違い

Swift 4.1flatMapは非推奨のようです。ただし、Swift 4.1compactMapには新しいメソッドがあり、同じことをしていますか? flatMapを使用すると、コレクション内の各オブジェクトを変換し、nilであったアイテムを削除できます。
flatMapと同様

let array = ["1", "2", nil] 
array.flatMap { $0 } // will return "1", "2"

compactMapと同様

let array = ["1", "2", nil] 
array.compactMap { $0 } // will return "1", "2"

compactMapは同じことをしています。

これら2つの方法の違いは何ですか?なぜAppleメソッドの名前を変更することに決めたのですか?

18
BilalReffas

flatMapには3つの異なるバリアントがあります。 Optional値を返すクロージャを受け入れるSequence.flatMap(_:)のバリアントは非推奨になりました。 SequenceとOptionalの両方でのflatMap(_:)の他のバリアントはそのままです。提案文書で説明されている理由は、誤用のためです。

廃止されたflatMapバリアント機能は、新しいメソッドcompactMapでまったく同じです。

詳細を参照してください こちら

18
Bilal

Swift標準ライブラリはflatMap関数の3つのオーバーロードを定義します:

Sequence.flatMap<S>(_: (Element) -> S) -> [S.Element]  
Optional.flatMap<U>(_: (Wrapped) -> U?) -> U?  
Sequence.flatMap<U>(_: (Element) -> U?) -> [U]  

最後のオーバーロード関数は、2つの方法で誤用される可能性があります。
次の構造体と配列を検討してください。

struct Person {
  var age: Int
  var name: String
}  

let people = [Person(age: 21, name: "Osame"), Person(age: 17, name: "Masoud"), Person(age: 20, name: "Mehdi")]  

最初の方法:追加のラッピングとアンラッピング:
people配列に含まれる人物の年齢の配列を取得する必要がある場合、次の2つの関数を使用できます。

let flatMappedAges = people.flatMap({$0.age})  // prints: [21, 17, 20]
let mappedAges = people.map({$0.age})  // prints: [21, 17, 20]  

この場合、map関数がジョブを実行し、両方が同じ結果を生成するため、flatMapを使用する必要はありません。さらに、このflatMapのユースケースには、無用のラッピングおよびアンラッピングプロセスがあります(クロージャーパラメーターは、返される値をOptionalでラップし、flatMapの実装は、返される前にOptional値をアンラップします)

2番目の方法-収集プロトコルへの文字列適合:
people配列から人物の名前のリストを取得する必要があると考えてください。次の行を使用できます。

let names = people.flatMap({$0.name})  

Swift 4.0より前のバージョンを使用していた場合、変換されたリストが得られます

["Osame", "Masoud", "Mehdi"]  

しかし、新しいバージョンではStringCollectionプロトコルに準拠しているため、flatMap()を使用すると、3番目の関数ではなく最初のオーバーロード関数と一致し、変換後のフラットな結果が得られます値:

["O", "s", "a", "m", "e", "M", "a", "s", "o", "u", "d", "M", "e", "h", "d", "i"]

結論:flatMap()の3番目のオーバーロードは廃止されました
これらの誤用のため、SwiftチームはflatMap関数への3番目のオーバーロードを廃止することを決定しました。そして、Optionalsに対処する必要がある場合のソリューションこれまでのところ、compactMap()と呼ばれる新しい関数を導入することで、期待される結果が得られます。

20
Mehdi