iPhone
 Computer >> コンピューター >  >> スマートフォン >> iPhone

Swift の Map、Filter、Reduce の舞台裏

関数は何らかの入力を受け取り、それに対して何かを行い、出力を作成します。関数には署名と本体があります。関数に同じ入力を与えると、常に同じ出力が得られます。つまり、関数 の定義です。 .

次に、関数を詳しく見ていくことで、関数について詳しく説明します。 Swift の高階関数について説明します。別の関数を入力として受け取ったり、関数を返したりする関数は呼び出されます 高階関数 .

Swift では、ma​​p、filter、reduce で遊んでいます 毎日。これらの関数を使用すると、まるで魔法のようです。この時点では、舞台裏で何が起こっているのか分からないかもしれません。 Map、Filter、Reduce は、関数型プログラミングのアイデアとアプローチを通じて機能します。 Swift は純粋な関数型言語ではありませんが、関数型のことを実行できます。

それでは、彼らのバックグラウンドで何が起こっているのかを 1 つずつ見ていきましょう。まず、いくつかの特定のデータ型に対してこれらの関数の基本バージョンを実装し、次に汎用バージョンの実装を試みます。

マップ機能

整数の配列があり、元の配列の各要素にデルタ値を追加した後に新しい配列を返す関数を書く必要があるとしましょう。以下のような単純な for ループを使用して、このための関数を簡単に書くことができます:

ここで、元の配列の各要素を 2 倍にして新しい配列を返す別の関数が必要です。このために、以下のように実装できます:

上記の 2 つの関数を見ると、基本的に同じことを行っていることがわかります。 for ループ内の機能のみが異なります。どちらも Integer を取ります 配列を入力として、for ループを使用して各要素を変換し、新しい配列を返します。したがって、基本的に重要なことは、各要素を新しいものに変換することです.

Swift は高階関数をサポートしているため、整数の配列を受け取り、その関数を入力として変換し、変換関数を元の配列の各要素に適用して新しい配列を返す関数を作成できます。

ただし、上記には問題があります。整数配列しか返されません。たとえば、入力整数配列を文字列配列に変換する必要がある場合、この関数ではそれを行うことができません。そのためには、どの型でも機能する汎用関数を作成する必要があります。

次のように、配列拡張でジェネリック関数を実装できます:

<オール>
  • ジェネリック型 T で動作する Array Extension でマップ関数を宣言します .
  • 関数は (Element) ->; 型の関数を取ります 入力としての T
  • T を保持する空の結果配列を宣言します 関数内の型のデータ。
  • それ自体を反復する for ループを実装し、変換関数を呼び出して要素を型 T に変換します。
  • 変換された値を結果の配列に追加します
  • これが地図です 関数は Swift で動作します。 ma​​p を実装する必要がある場合 関数, 次に、上記のように実装します。したがって、基本的に、配列内で魔法が発生することはありません — 自分で関数を簡単に定義できたはずです。

    フィルター機能

    整数の配列があり、配列に偶数のみを保持したいとします。シンプルな for ループを使用してこれを実装できます:

    ここで、プロジェクトのクラス ファイル名を表す文字列の配列があり、. のみを保持したいとします。 素早い ファイル。これは、以下のような 1 つのループでも実行できます:

    上記の 2 つの関数の実装を詳しく調べると、基本的に同じことを行うことがわかります。2 つの配列のデータ型だけが異なります。配列と関数を入力として取り、includeElement の出力に依存する汎用フィルター関数を実装することで、これを一般化できます。 関数で、結果の配列に要素を追加するかどうかを決定します。

    Reduce 関数

    整数の配列があり、要素の合計と積を返す 2 つの関数を実装したいとします。シンプルな for ループを使用してこれを実装できます:

    整数の配列を持つ代わりに、文字列の配列があり、配列内のすべての要素を連結したいとします:

    3 つの関数はすべて、基本的に同じことを行います。配列を入力として取り、結果の変数を初期化し、配列を反復処理し、結果の変数を更新します。

    ここから、すべてに対して機能する汎用関数を実装できます。これを行うには、結果の変数の初期値と、反復ごとにその変数を更新する関数が必要です。

    したがって、次の定義でジェネリック関数を実装できます:

    上記の実装は、[Element] 型の入力配列に対して一般的です。 タイプ T の結果を計算します .機能するには、タイプ T の初期値が必要です 結果の変数に割り当てます。次に、タイプ (T, Element) -> の関数が必要です T は、結果の変数を更新するために各反復の for ループ内で使用されます。

    読んでくれてありがとう!


    1. Swift での関数合成の簡単な紹介

      プログラマーは毎日関数に遭遇します。関数は特別なタイプの関係を表します。関数が受け取るすべての入力値は、何らかの出力値に関連付けられています。したがって、より一般的に言えば、関数は、いくつかの入力値を 1 つの出力値にマップする規則です。 関数合成の背後にある基本的な考え方は、ある関数を別の関数の結果に適用することです。つまり、関数を 1 つの関数に結合するという数学的な概念です。 関数構成 はじめに 数学的概念と一緒に議論しましょう。上の図では、「f」と「g」が 2 つの関数です。関数は次のように表すことができます: f: A -> Bg: B -> C この 2 つの関数

    2. Generics と Swift の Any 型の違いを分析しましょう

      Swift は、現在最もタイプセーフな言語の 1 つです。 ??? ああ、待って!!言語が型安全であるとはどういう意味ですか? ? 型安全な言語により、その時点で利用可能な適切な種類のデータで操作が機能することが常に保証されます。✓ 言語にさまざまなデータ型 (例:Int、Float、String、Array、Dictionary) を宣言する機能があり、特定のデータ型で宣言された変数が異なる種類の変数を決して保持しないようにする機能もある場合。 型安全な言語では、型チェックは常に行われます。言語によっては、コンパイル時または実行時に発生する可能性があります.✅ さて、Swift