4

次のように Array に拡張メソッドを追加しようとしています。

extension Array {
    func contains(obj: T) -> Bool {
        let filtered = self.filter {$0 == obj}
        return filtered.count > 0
    }
}

しかし、self.filter {$0 == obj}働かないでください。コンパイラ エラー:

指定された引数を受け入れる「==」のオーバーロードが見つかりませんでした

4

5 に答える 5

13

スウィフト 1.x

コメントで述べたように、contains機能があります。ただし、拡張機能の作成方法とコンパイラ エラーの意味に関する質問に答えるには、次のようにします。

配列内の要素は必ずしも と比較できるとは限りません==。パラメータがEquatable同じであることを確認する必要があり、配列要素が同じタイプであることを確認する必要があります。

extension Array {
    func contains<T : Equatable>(obj: T) -> Bool {
        let filtered = self.filter {$0 as? T == obj}
        return filtered.count > 0
    }
}

Swift 2/Xcode 7 (ベータ)

Swift 2 にはSequenceType.contains、まさに作成しようとしていた が含まれています。

これは、メソッドを特定の (Equatable などの) 型引数に制限できる Swift 構文によって可能になります。次のようになります。

extension SequenceType where Generator.Element: Equatable {
    func contains(element: Self.Generator.Element) -> Bool {
        ...
    }
}
于 2014-06-06T21:42:34.450 に答える
1

組み込みの contains が参照型で機能しないことがわかりました。これが必要で、以下のコードで解決しました。私のように、他の誰かが contains() について混乱している可能性があるため、ここに貼り付けます。

extension Array {
    func containsReference(obj: AnyObject) -> Bool {
        for ownedItem in self {
            if let ownedObject: AnyObject = ownedItem as? AnyObject {
                if (ownedObject === obj) {
                    return true
                }
            }
        }

        return false
    }
} 
于 2015-05-06T21:13:28.833 に答える
1

これは、参照型の Swift 2.1 で非常にうまく機能します。

extension SequenceType where Generator.Element: AnyObject {
    func contains(obj: Self.Generator.Element?) -> Bool {
        if obj != nil {
            for item in self {
                if item === obj {
                    return true
                }
            }
        }
        return false
    }
}

値の型の場合、これを追加できます:

extension SequenceType where Generator.Element: Equatable {
    func contains(val: Self.Generator.Element?) -> Bool {
        if val != nil {
            for item in self {
                if item == val {
                    return true
                }
            }
        }
        return false
    }
}
于 2015-11-11T20:12:36.450 に答える
0

完全ではありませんが、 nschum の回答に基づいて構築されたこのバージョンは、オプションの引数 (オプションの型の配列ではありません) もサポートしています。

extension Array {

    private func typeIsOptional() -> Bool {
        return reflect(self[0]).disposition == .Optional
    }

    func contains<U : Equatable>(obj: U) -> Bool {
        if isEmpty {
            return false
        }

        if (typeIsOptional()) {
            NSException(name:"Not supported", reason: "Optional Array types not supported", userInfo: nil).raise()
        }

        // cast type of array to type of argument to make it equatable
        for item in self.map({ $0 as? U }) {
            if item == obj {
                return true
            }
        }

        return false
    }

    // without this version, contains("foo" as String?) won't compile
    func contains<U : Equatable>(obj: U?) -> Bool {
        if isEmpty {
            return false
        }

        if (typeIsOptional()) {
            NSException(name:"Not supported", reason: "Optional Array types not supported", userInfo: nil).raise()
        }

        return obj != nil && contains(obj!)
    }

}

オプションの配列がある場合、jtbandes のおかげで、このグローバル関数を使用して、非オプション (nil 引数が削除された) を含む配列のコピーを取得できます。

func unwrapOptionals<T>(a: [T?]) -> [T] {
    return a.filter { $0 != nil }.map { $0! }
}

使用法:

 1>     func unwrapOptionals<T>(a: [T?]) -> [T] {
  2.         return a.filter { $0 != nil }.map { $0! }
  3.     }
  4>
  5> let foo = ["foo" as String?]
foo: [String?] = 1 value {
  [0] = "foo"
}
  6> let bar = unwrapOptionals(foo)
bar: [String] = 1 value {
  [0] = "foo"
}

適切な対策として、型がオプションでない場合に配列を返すものを追加します。unwrapOptionals()このようにして、オプションではない配列を呼び出した場合の実行時エラーを回避します。

func unwrapOptionals<T>(a: [T]) -> [T] {
    return a
}

unwrapOptionals内部で呼び出すことができると思うかもしれませんfunc contains<U : Equatable>(obj: U?)。ただし、Element配列拡張の型は単なる型であるため、これは機能しません。オプションの型であることを「認識」していません。したがって、 を呼び出すunwrapOptionalsと、2 番目のバージョンが呼び出され、オプションでいっぱいの配列が返されます。

于 2015-02-07T05:33:38.993 に答える