私は値がSwiftのRange
内にあるかどうかを判断する方法を理解しようとしています。
基本的に私がやろうとしていることは、switchステートメントの例の1つを次のようなものに適応させることです。
let point = (1, -1)
switch point {
case let (x, y) where (0..5).contains(x):
println("(\(x), \(y)) has an x val between 0 and 5.")
default:
println("This point has an x val outside 0 and 5.")
}
私の知る限り、上記の架空の.contains
メソッドが実行する組み込みの方法はありません。
そこで、Range
クラスを拡張しようとしました。しかし、私はジェネリックの問題にぶつかることになりました。 Range<Int>
を拡張できないため、Range
自体を拡張する必要がありました。
私が得た最も近いものはこれでしたが、ForwardIndex
に対して>=
および<=
が定義されていないため、機能しません
extension Range {
func contains(val:ForwardIndex) -> Bool {
return val >= self.startIndex && val <= self.endIndex
}
}
Range
に.contains
メソッドを追加するにはどうすればよいですか?または、値が範囲内にあるかどうかを判断するより良い方法はありますか?
Edit2:これはRange
を拡張するように機能するようです
extension Range {
func contains(val:T) -> Bool {
for x in self {
if(x == val) {
return true
}
}
return false
}
}
var a = 0..5
a.contains(3) // true
a.contains(6) // false
a.contains(-5) // false
ただし、以下で説明する〜=演算子に非常に興味があります。今それを調べています。
~=
演算子を使用してそれを行うことができます:
let point = (1, -1)
switch point {
case let (x, y) where (0..5) ~= x:
println("(\(x), \(y)) has an x val between 0 and 5.")
default:
println("This point has an x val outside 0 and 5.")
}
スイッチで直接行うこともできます。
let point = (1, -1)
let (x, y) = point
switch x {
case 0..5:
println("yes")
default:
println("no")
}
~=
は、caseステートメントで使用されるパターン一致演算子です。詳細を見る ドキュメント内 。
Swift 5では、必要に応じて、次のオプションのいずれかを選択して、Range
(またはClosedRange
)に値が含まれているかどうかを判断できます。
contains(_:)
メソッドRange
、ClosedRange
、CountableRange
およびCountableClosedRange
にはcontains(_:)
メソッドがあります。 Range
contains(_:)
メソッドには次の宣言があります。
_func contains(_ element: Bound) -> Bool
_
指定された要素が範囲内に含まれているかどうかを示すブール値を返します。
使用法:
_let value: Int = 0
let range = -200 ..< 300
print(range.contains(value)) // prints true
_
~=(_:_:)
演算子Range
、ClosedRange
、CountableRange
およびCountableClosedRange
には~=(_:_:)
演算子があります。 Range
~=(_:_:)
演算子には次の宣言があります:
_static func ~= (pattern: Range<Bound>, value: Bound) -> Bool
_
値が範囲に含まれているかどうかを示すブール値を返します。
使用法:
_let value = 0
let range = -200 ..< 300
print(range ~= value) // prints true
_
Range
、ClosedRange
、CountableRange
、またはCountableClosedRange
に値が含まれているかどうかをテストする簡単な方法は、switchステートメントを使用することです。
_let value = 0
switch value {
case -200 ..< 300:
print("OK") // prints "OK"
default:
break
}
_
if case
_によるパターンマッチング前のswitchステートメントの代わりに、_if case
_を使用できます。
_let value = 0
if case -200 ..< 300 = value {
print("OK") // prints "OK"
}
_
したがって、問題を解決するには、次のオプションのいずれかを使用できます。
_let point = (1, -1)
switch point {
case let (x, y) where (0 ..< 5).contains(x):
print("(\(x), \(y)) has an x val between 0 and 5.")
default:
print("This point has an x val outside 0 and 5.")
}
_
_let point = (1, -1)
if case let (x, y) = point, 0 ..< 5 ~= x {
print("(\(x), \(y)) has an x val between 0 and 5.")
}
_
Rangeをいじる代わりに、次のような単純なヘルパー関数を追加できます。
let point = (1, -1)
switch point {
case let (x, y) where contains((0..5),x):
println("(\(x), \(y)) has an x val between 0 and 5.")
default:
println("This point has an x val outside 0 and 5.")
}
func contains(range :Range<Int>, x: Int)->Bool{
for num in range{
if(num==x){
return true
}
}
return false
}
おそらくクロージャーでも同様のことができます。
contains
のRange
拡張を記述する場合は、distanceTo
のForwardIndex
を使用して、指定された値が範囲内にあるかどうかを判断します。
また、パラメータのタイプとして、一般的なプロトコルElement
ではなく、特定のタイプFowardIndex
を使用します。
distanceTo
とElement
はどちらもRange
定義の一部です。
extension Range {
func contains(element: Element) -> Bool {
return startIndex.distanceTo(element) >= 0 && element.distanceTo(endIndex) > 0
}
}
さらに、Range
にはすでにextension SequenceType where Generator.Element : Equatable
のcontains
メソッドがあります。したがって、自分で作成せずに使用することができます。
私は同じことを見て、やった:
let r = 7...9
operator infix ~ {}
func ~ (range:Range<Int>, item:Int) -> Bool{
return item >= range.startIndex && item <= range.endIndex - 1
}
r ~ 9
それから私は〜=が同じことをするのを見ました!