确定Range是否包含值

时间:2014-06-03 20:53:09

标签: swift range

我正试图找出一种方法来确定一个值是否落在Swift的Range范围内。

基本上我正在尝试做的是调整其中一个switch语句示例来做这样的事情:

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
    }
}

如何向.contains添加Range方法?或者是否有更好的方法来确定某个值是否在一个范围内?

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

我对下面提到的〜=运算符非常感兴趣;现在正在调查。

5 个答案:

答案 0 :(得分:39)

您可以使用~=运算符执行此操作:

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语句使用的模式匹配运算符。详情请见in the docs

答案 1 :(得分:24)

使用Swift 3,根据您的需要,您可以选择以下选项之一来确定RangeClosedRangeCountableRange还是CountableClosedRange包含一个值。

1。 contains(_:)方法

RangeClosedRangeCountableRangeCountableClosedRange使用contains(_:)方法。 Range contains(_:)方法具有以下声明:

func contains(_ element: Bound) -> Bool
  

返回一个布尔值,指示给定元素是否包含在范围内。

用法:

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

2。 ~=(_:_:)运营商

RangeClosedRangeCountableRangeCountableClosedRange都有~=(_:_:)运营商。 Range ~=(_:_:)运算符具有以下声明:

static func ~=(Range<Bound>, Bound)
  

返回一个布尔值,指示值是否包含在范围内。

用法:

let value = 0
let range: Range<Int> = -200 ..< 300
print(range ~= value) // prints true

3。切换声明

测试RangeClosedRangeCountableRangeCountableClosedRange是否包含值的简单方法是使用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.")
}

答案 2 :(得分:3)

您可以添加一个像这样的简单辅助函数

,而不是搞乱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 :(得分:2)

如果您想写contains Range的{​​{1}}扩展名,请使用distanceTo的{​​{1}}来确定给定值是否在范围内。

还可以使用特定类型ForwardIndex代替通用协议Element作为参数类型。

FowardIndexdistanceTo都是Element定义的一部分。

Range

Plus extension Range { func contains(element: Element) -> Bool { return startIndex.distanceTo(element) >= 0 && element.distanceTo(endIndex) > 0 } } 已有来自Range的{​​{1}}方法。所以你可以自己使用它而不用自己写一个。

答案 4 :(得分:1)

我看着同样的事情并做了:

let r = 7...9

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

r ~ 9

然后我看到〜=做同样的事情!