web-dev-qa-db-ja.com

Rangeに値が含まれているかどうかを判別する

私は値が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

ただし、以下で説明する〜=演算子に非常に興味があります。今それを調べています。

25
Brad Dwyer

~=演算子を使用してそれを行うことができます:

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ステートメントで使用されるパターン一致演算子です。詳細を見る ドキュメント内

39
gwcoffey

Swift 5では、必要に応じて、次のオプションのいずれかを選択して、Range(またはClosedRange)に値が含まれているかどうかを判断できます。


1. contains(_:)メソッド

RangeClosedRangeCountableRangeおよびCountableClosedRangeにはcontains(_:)メソッドがあります。 Rangecontains(_:) メソッドには次の宣言があります。

_func contains(_ element: Bound) -> Bool
_

指定された要素が範囲内に含まれているかどうかを示すブール値を返します。

使用法:

_let value: Int = 0
let range = -200 ..< 300
print(range.contains(value)) // prints true
_

2. ~=(_:_:)演算子

RangeClosedRangeCountableRangeおよびCountableClosedRangeには~=(_:_:)演算子があります。 Range~=(_:_:) 演算子には次の宣言があります:

_static func ~= (pattern: Range<Bound>, value: Bound) -> Bool
_

値が範囲に含まれているかどうかを示すブール値を返します。

使用法:

_let value = 0
let range = -200 ..< 300
print(range ~= value) // prints true
_

3. switchステートメント

RangeClosedRangeCountableRange、またはCountableClosedRangeに値が含まれているかどうかをテストする簡単な方法は、switchステートメントを使用することです。

_let value = 0
switch value {
case -200 ..< 300:
    print("OK") // prints "OK"
default:
    break
}
_

4. _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.")
}
_
26
Imanou Petit

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
}

おそらくクロージャーでも同様のことができます。

3
Connor

containsRange拡張を記述する場合は、distanceToForwardIndexを使用して、指定された値が範囲内にあるかどうかを判断します。

また、パラメータのタイプとして、一般的なプロトコルElementではなく、特定のタイプFowardIndexを使用します。

distanceToElementはどちらもRange定義の一部です。

extension Range {

    func contains(element: Element) -> Bool {
        return startIndex.distanceTo(element) >= 0 && element.distanceTo(endIndex) > 0
    }

}

さらに、Rangeにはすでにextension SequenceType where Generator.Element : Equatablecontainsメソッドがあります。したがって、自分で作成せずに使用することができます。

2
Medo Paw

私は同じことを見て、やった:

let r = 7...9

operator infix ~ {}
func ~ (range:Range<Int>, item:Int) -> Bool{
  return item >= range.startIndex  && item <= range.endIndex - 1
}

r ~ 9

それから私は〜=が同じことをするのを見ました!

1
thisispete