Reinder de Vriesによって2020年7月12日にSwiftのアプリ開発で書かれました

FlatMapとCompactMapはSwift

で説明されていますSwiftにはコレクションやシーケンスの変換に便利な関数がたくさんあります。 このチュートリアルでは、map(_:)flatMap(_:)compactMap(_:)について説明します。

ここでは、私たちが焦点を当てるものです:

  1. map(_:)クロージャを適用してコレクションまたはシーケンスを変換する方法
  2. flatMap(_:)を呼び出した後に入力配列をフラット化する方法map(_:)
  3. compactMap(_:)が入力配列からnilを削除する方法

前のチュートリアルでは、

を使用する方法について説明しました。1699>とreduce(_:)。 これらの高階関数は、簡潔で洞察に満ちた方法でコレクションを変換するのに非常に役立ちます。

準備はできましたか? 行こう

  1. SwiftでMap関数を使用する
  2. FlatMap関数を使用する
  3. CompactMap関数を使用する
  4. なぜFlatMapとCompactMapを使用するのですか?
  5. 続きを読む

クロージャや高次関数にはまだ慣れていませんか? それらの最初に読むことを確認してください:

  • Swiftでのクロージャの究極のガイド
  • Swiftでのマップ、縮小、およびフィルタ

Swift

のMap関数を使用して、Swiftの高次関数の簡単な復習として、私たちの出発点はmap(_:)関数です。 この関数は、配列や辞書のように、シーケンス内の各要素に変換を適用します。

ここに例があります:

let numbers=
let result=numbers.地図({ $0 * $0 })
印刷(結果)
警告を隠す

それを分解してみましょう:

まず、いくつかの整数値を持つ配列numbersを作成しています。 次に、関数map(_:)numbersで呼び出され、その結果がresultに割り当てられます。

map(_:)関数には、の結果を返すクロージャというパラメータがあります。 は、クロージャの最初のパラメータ、つまり変換されているnumbersからの数値に対応します。

私たちはnumbersのすべての数の二乗を計算しています。 本質的には、演算numbers内のすべての数値で呼び出され、結果の配列はresultに割り当てられます。 ある配列を別の配列に変換するか、”マッピング”しています。

map(_:)で配列を変換することは、forループを使用するのと似ていますが、はるかに簡潔です。 このように:

let numbers = var result = ()for number in numbers { result += }print(result)

これを見る別の方法があります。 map(_:)を使用すると、数値の入力配列は別の数値配列に変換されます。 このように:

2 => 2 * 2 => 43 => 3 * 3 => 94 => 4 * 4 => 165 => 5 * 5 => 25

map(_:)のような関数は、通常の値とは対照的に入力として関数を取るため、高次関数と呼ばれます。 高階関数は関数を出力することもでき、これは関数型プログラミングと呼ばれるプログラミングパラダイムに有用である。

技術的には、任意のシーケンスでmap(_:)のような高次関数を呼び出すことができます。 これには、配列、辞書、セットのようなコレクション、1...100のような範囲、いわゆるイテレータが含まれます。 基本的には、値の「リスト」のように見えるもの。

このチュートリアルの最後で、なぜ高階関数が有用なのかについて説明します。 まず、flatMap(_:)compactMap(_:)について学びましょう。

Ios開発者として雇われる

Swift5でiOS14アプリを構築する方法を学ぶ

私のiOS開発コースにサインアップし、プロのiOS開発者としてのキャリアを開始す

FlatMap関数

を使用すると、flatMap(_:)関数は、結果の配列を”フラット化”することを除いて、map(_:)に似ています。 ここに例があります:

let numbers=,,]
let result=numbers.flatMap({$0})
print(result)
警告を隠す

上記のコードは、整数のネストされた配列から始まります。 numbers配列は、3つの配列の配列で構成され、それぞれに3つの数値が含まれています。

クロージャ{ }は、単にクロージャの最初の引数、すなわち個々のネストされた配列を返します。 変換や操作は行われていません。 ただし、numbers配列でflatMap(_:)を呼び出すと、map(_:)ではなく、個々の数字のフラット化された配列になります。 入力配列numbersとは異なり、結果配列にはネストされた配列が含まれていません!

別の例を見てみましょう。 あなたがキリンの4つのグループで作業していて、特定の高さよりも背の高いキリンの単一のグループを作成したいと想像してください。 ここでは、それを行う方法です:

キリン=,,]
キリン=,,]
キリン=,,]
キリン=,,]
キリン=,,]flatMap({$0.フィルター({ $0 > 10 }) })
プリント(一番背の高い)
警告を隠す

giraffesに配列の配列が含まれている方法を参照してください。 上記のコードでは、関数filter(_:)giraffes内のすべてのネストされた配列で呼び出されます。 私たちは整数だけをしたいです(キリン!)より大きい10。 結果の配列は、1つの「フラット」配列に平坦化され、tallestに割り当てられます。

flatMap(_:)の代わりにmap(_:)を使用した場合、どうなるか考えてみてください。 結果の配列は平坦化されません。 代わりに、それはこれだろう:

, , ]

flatMap(_:)関数は、最初に配列項目に対してmap(_:)を呼び出し、次にそれをフラット化することに注意することが重要です。 そのため、次のようなものが機能しません:

let numbers = , , ]let result = numbers.flatMap({  * 2 })

上記のコードでは、はnumbers内の配列を参照しています。 配列に2を乗算することは不可能なので、このコードは機能しません。

フラットマッピングについては、一つの次元の配列を見ると考えるのが賢明です。 2次元の配列から始まり、flatMap(_:)の後に1次元の配列になります。

オプションでflatMap(_:)を使用するのはどうですか? 次にそれを見てみましょう。

“compact map”という名前は、配列からnil項目を削除すると配列がよりコンパクトになるという考えに基づいています。 同様に、”flat map”という名前は、配列を平坦化することから来ています。 そして、「マッピング」は数学の概念であり、あるセットの値を別のセットに関連付けることができます。

CompactMap関数

を使用すると、compactMap(_:)関数は入力配列からnil値を削除します。 Optionalsで作業するとき、それは超便利です。

スウィフト4の前に。図1に示すように、flatMap(_:)関数(上記)を使用して、フラット化された配列からnil値をフィルタリングすることもできます。 Swift4.1以降では、この目的のために明示的なcompactMap(_:)を使用するようになりました。

ここに例があります:

let numbers=
let result=numbers.compactMap({Int($0)})
print(result)
警告を非表示にする

何が起こるかを参照してください。 コードの最も重要な部分はInt()です。 これは、numbersからで個々の文字列を受け取り、Int()初期化子を使用して整数に変換しようとします。

このInt()初期化子は失敗可能です:それはnilを返すことができます–オプション–その戻り値の型はInt?です。 その結果、マッピング変換の戻り値の型は–オプションの整数の配列です。

compactMap(_:)関数は、map(_:)を呼び出した後、返された配列からnil要素を自動的に削除します。 そのため、戻り値の型は省略可能ではありません。上記のコードでは、resultのタイプはです。 map(_:)を使用した場合、戻り値の型はになります。 そして、あなたはそれらを扱うために、配列から値をアンラップするための余分なステップが必要だったでしょう。

なぜFlatMapとCompactMapを使用するのですか?

flatmapとcompactmapの実際の使用例を議論する前に、これらの高階関数とその目的を簡単に要約しましょう。

  1. map(_:)関数は入力コレクションにクロージャを適用し、変換されたコレクションを返します
  2. flatMap(_:)関数は同じことを行い、結果のコレクションもフラット化します
  3. compactMap(_:)関数はmap(_:)と同じことを行い、結果のコレクションからnilを削除します

抽象的にmap(_:)flatMap(_:)compactMap(_:)を使用すると、実際のユースケースを想像するのが難しいことがあります。 あなたがそれらを使用したいと思う理由を議論してみましょう。

map(_:)のような関数を使用してシーケンスに変換を適用するには、いくつかの利点があります:

  • 一時変数と複数行のfor in { }ブロックは必要ないため、forループを使用するよりも簡潔です。
  • 通常、map(_:)への呼び出しを1行で書くことができます。
  • map(_:)のような関数を連鎖させることができるので、シーケンスに複数の変換を一つずつ適用することができます。

一般に、高階関数は値のシーケンスに関数を適用できるため便利です。 変換を手続き的にコーディングする代わりに、関数を適用して結果を返すことができます。

flatMap(_:)の最も実用的なユースケースは、グループ化またはネストされた入力値を扱うことですが、必要な出力値は一次元である必要があります。

たとえば、音楽アプリでは、曲、アーティスト、プレイリストの3つの配列を持つことができます。 それらを1つの配列に結合し、その上でflatMap(_:)を呼び出し、isFavoritetrueである曲、アーティスト、プレイリストを選択し、お気に入りの項目のフラットリストが1つにな

compactMap(_:)の実用的なユースケースは、nilを返すことができる変換で作業しています。 compactMap(_:)nilの値をすぐに除外させることで、いくつかの簡単な手順を節約できます。 これと比較して、nilを除外した場合、filter(_:)関数はオプションの値を返しました。

flatMap(_:)compactMap(_:)、さらにはfilter(_:)またはreduce(_:_:)を組み合わせることができます。 ソーシャルメディアアプリを構築しているとします。 ユーザーの投稿のタイムラインを作成する必要があります。 3つのクエリを使用して、フォロワーの投稿、広告、トレンドトピックなど、ユーザーの投稿Idを選択します。

  • map(_:)を使用してこれらのIdを実際のPostオブジェクトに展開できます
  • flatMap(_:)を使用して3つのグループを1つのコレクションにフラット化できます
  • compactMap(_:)を使用して、展開できなかった投稿を破棄できます

Neat!

Ios開発者として雇われる

Swift5でiOS14アプリを構築する方法を学ぶ

私のiOS開発コースにサインアップし、プロのiOS開発者としてのキャリアを開始す

さらに読む

コードをより簡潔で読みやすくするため、map(_:)flatMap(_:)compactMap(_:)について学ぶことは価値があります。 アプリのコードに関数型プログラミングを追加できます。 あなたがそれらに慣れると、あなたはそれらなしであなたの仕事をすることができると信じることができません。

特にmap(_:)flatMap(_:)compactMap(_:)の違いは指摘する価値があります。 最初の1つはシーケンスに変換を適用し、2番目の1つは結果の配列を平坦化し、3番目の1つは結果を返す前にnil値を削除します。 すごい!

コメントを残す

メールアドレスが公開されることはありません。