我正试图找出一种方法来确定一个值是否落在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
我对下面提到的〜=运算符非常感兴趣;现在正在调查。
答案 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,根据您的需要,您可以选择以下选项之一来确定Range
,ClosedRange
,CountableRange
还是CountableClosedRange
包含一个值。
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 ~=(Range<Bound>, Bound)
返回一个布尔值,指示值是否包含在范围内。
用法:
let value = 0
let range: Range<Int> = -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.")
}
答案 2 :(得分:3)
您可以添加一个像这样的简单辅助函数
,而不是搞乱Rangelet 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
作为参数类型。
FowardIndex
和distanceTo
都是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
然后我看到〜=做同样的事情!