web-dev-qa-db-ja.com

Swiftの配列の一般的な拡張

非常に率直に言うと、拡張機能の作成と使用法を学ぶのはまったく新しいです。

カテゴリ全体(Swift 3.0)の拡張)を作成したかったので、アプリケーション全体でArrayに対して繰り返し操作を実行できます。

サンプルリンク1

これは私が調査をしている間に見、理解したことであり、別の拡張を作成するために必要なデータ型に基づくのではなく、一般的なはずのさまざまな方法で拡張を作成したかったのです。

上記の例では、特定のデータ型ごとの拡張を行う場合、単一の拡張を作成する必要があります。一般的なカテゴリ(Extension in Swift)を作成する方法がある場合は、ガイダンスが必要でした。

  1. extension _ArrayType where Generator.Element == Int
  2. extension Array where Element: Equatable
  3. extension Array where Element == Int
  4. extension _ArrayType where Generator.Element == Float
  5. extension SequenceType where Self.Generator.Element: FloatingPointType
  6. extension Array where Element: DoubleValue
  7. extension Sequence where Iterator.Element == String

、等...

サンプルリンク2

注:つまり、に基づいてアクションを実行したいと考えることができます上記の要件に従って、各データ型の単一の拡張を作成するのではなく、単一の拡張のArray

14
Jignesh Fadadu

コメントで述べたように、これを達成する1つの方法は、カバーしたい型が採用する独自のプロトコルを作成することです(コメントではContentと呼ばれ、この例では以下で使用されます)(from 最初のソース ):

protocol Content {
    var hash: String { get }
}
extension Array where Element : Content {

    func filterWithId(id : String) -> [Element] {
        return self.filter { (item) -> Bool in
            return item.id == id
        }
    }
}

しかし、元の質問は主に配列の一般的な拡張について尋ねているようですが、1つのコメントでは不可能であるとしていますが、Swiftで100%可能です(これは大きなSwift機能、実際には( second source から)。

たとえば、Intsのみに特定の拡張メソッドを定義する場合は、次のようにできます。

extension Sequence where Iterator.Element == Int {
    var sum: Int {
        return reduce(0, +)
    }
}

質問の元の要件は、データ型にとらわれない可能性がある拡張メソッドであるため、共通に保つ必要があるようです。私が正しく理解していれば、これらのデータ型は一般にEquatableHashableにある程度準拠しているようです。これは、この種のジェネリックスタッフが機能するための最小要件です。ただし、この要素の適合性により、次のことが可能になります。

extension Sequence where Iterator.Element is Equatable {
    func extensionMethodName<T: Equatable>(_ input: [T], singleElement: T) -> [T] {
        // T is now a generic array of equatable items. You can implement whatever extension logic you need with these. 
        // I added different ways of passing in and returning this generic type, but the only thing that is likely going to be consistent is the `<T: Equatable>` which is Swift standard syntax for declaring generic type parameters for a method.
    }
}

Swift構文はすばやく変更され、ここにあるものはすぐに古くなる可能性がありますが、 このガイド はAppleおよび^の上で使用されるGenericsの最新の構文を示します。

私の答えは、上記の例/構文で使用されているいくつかのStackOverflowの質問/回答から引用しています。ソース: (SO Source)(SO Source 2)

要約すると、すべてのArray型の一般的な関数/変数の両方を持ち、型固有の拡張のオーバーライドがまだある完全にカスタムの拡張ソリューションでは、上記のすべてのメソッドを組み合わせることができます。

12
BHendricks

Where句では、「エレメントタイプにこれらのルールがある場合、この拡張を検討する」を指定します。

すべての拡張機能ですべてのメソッドを実装する必要はありません。

例えば:

  • _Array<Element>_を拡張して、通常はメソッドfoo(_:Element)を使用する場合:

    _extension Array {
        func foo(bar: Element) { /*your code goes here */ }
    }
    _
  • ElementがEquatableIntDoubleおよび...またはEquatableとしてマークした構造体/クラスを含む)を実装した_Array<Element>_を拡張したい場合:

    _extension Array where Element: Equatable {
        func find(value: Element) -> Bool { 
            return index(of: value) != nil
        }
    }
    _
  • SequenceElementである場合にNumericを拡張し、get専用の変数sumを使用する場合:

    _extension Sequence where Element: Numeric {
        var sum: Element { 
            return reduce(0, +)
        }
    }
    _
  • _Collection<Collection<Element: Equatable>>_を拡張して、2Dコレクションと比較するメソッドを用意します。

    _extension Collection
        where Iterator.Element: Collection, 
        Iterator.Element.Iterator.Element: Equatable {
    
        func compare(to: Self) -> Bool {
            let flattenSelf = self.reduce([], +)
            let flattenTo = to.reduce([], +)
    
            return flattenSelf.count == flattenTo.count &&
                Zip(flattenSelf, flattenTo).reduce(true) { $0 && $1.0 == $1.1 }
        }
    }
    _

sortfindなどのメソッドを使用するために配列またはコレクションを拡張する必要はありません。これらのメソッドのほとんどは、_Element: Equatable_または_Element: Comparable_の場合、コンパイラー内ですでに拡張されています。 mapfilterreduceを使用すると、コードをあまり必要とせずに、より複雑な構造を実現できます。

10
farzadshbfn