Tupleの配列でcontainsが簡単に使えなかったので、少し試してみました。
Array<(Int, Int)>
型でやりました。
#現状
tupleArray
(Array<(Int, Int)>
型)の中に(0, 0)
があるかを調べたかったら、このように書く必要があります。
let tupleArray = [(0, 0), (5, 5)]
tupleArray.contains { t -> Bool in
t.0 == 0 && t.1 == 0
}
// true
使いづらいです。
普通のArray
([Int], [String]
)だったら、
let intArray = [1, 2, 3]
intArray.contains(2) // true
と簡潔に書けるのに。。。
#方法
演算子の定義を行い、さらに、SequenceType
にExtension
を与えます。
func == <T: Equatable, U: Equatable>(lhs: (T, U), rhs: (T, U)) -> Bool {
return lhs.0 == rhs.0 && lhs.1 == rhs.1
}
extension SequenceType where Self.Generator.Element == (Int, Int) {
func contains(element: (Int, Int)) -> Bool {
return contains { $0 == element }
}
}
すると、
tupleArray.contains((0, 0)) // true
tupleArray.contains((5, 0)) // false
このように見やすく書けるようになりました。
#質問
一般化しようとして、
extension SequenceType {
func contains<T, U where T: Equatable, U: Equatable, Self.Generator.Element == (T, U)>(element: (T, U)) -> Bool {
return contains { $0 == element }
}
}
と書いたのですが、
error: cannot convert value of type '(T, U) -> Bool' to expected argument type '_ -> Bool'
return contains { $0 == element }
^~~~~~~~~~~~~~~~~~~
このようなエラーが出てきてしまいます。
また、
extension SequenceType where T: Equatable, U: Equatable, Self.Generator.Element == (T, U) {
}
extension
に対して genericsを使ったwhere文で型を指定する方法も分かりませんでした。
解決策、なにかアドバイスをいただけると とてもうれしいです。
よろしくお願いします。
追記
Qiitaでのコメント、Swift Slackでのご回答ありがとうございました。
根本的な原因は分かりませんでしたが、==
演算子だけを定義し、
この書き方で妥協すれば汎用的に(T: Equatable, U: Equatable)
に対応できます。
func == <T: Equatable, U: Equatable>(lhs: (T, U), rhs: (T, U)) -> Bool {
return lhs.0 == rhs.0 && lhs.1 == rhs.1
}
let tupleArray2 = [("a", 1), ("b", 2)]
tupleArray2.contains { $0 == ("a", 1) } // true
tupleArray2.contains { $0 == ("c", 1) } // false
#参考
stackoverflow -> how-do-i-check-if-an-array-of-tuples-contains-a-particular-one-in-swift