美文网首页
范围操作符 单边范围操作符

范围操作符 单边范围操作符

作者: 曹来东 | 来源:发表于2018-09-26 08:28 被阅读5次

在Swift编程语言中引入了范围操作符这种非常方便实用的操作符。范围操作符可用于 for-in 循环迭代、获取一个数组的子数组、获取一个字符串的子串、[case 语句中的区间匹配]等场合。Swift中的范围操作符有两种:一种是闭区间范围操作符(...),其类型一般为 ClosedRange<Bound : Comparable>。比如,a ... b 表示范围从a到b,用数学来表示就是[a, b]。还有一种就是半开区间范围操作符(..<),其类型一般为 Range<Bound : Comparable>。比如, a ..< b 表示范围从a到b,但不包括b,用数学来表示就是[a, b)。这两种类型都是属于结构体类型。

范围操作符具有两个操作数,其操作数类型必须遵循 Comparable 协议,即要能比较出大小的。在Swift的基本类型中,像整数类型、浮点数类型、字符类型以及字符串类型都能作为范围操作符的操作数,而布尔类型则不行。范围操作符的左操作数必须小于等于右操作数,否则将会导致运行时异常。对于半开区间的范围操作符,如果左操作数的值等于右操作数,那么该范围将是一个空范围。如果闭区间范围操作符 ... 的操作数是一个整数类型,那么该范围操作符的类型将会是 CountableClosedRange;而如果半开区间范围操作符 ..< 的操作数是一个整数类型,那么该范围操作符的类型将会是 CountableRange。由于一般的 ClosedRange 与 Range 它们没有遵循 Sequence 协议,所以它们的对象不能用于 for-in 循环迭代。而 CountableClosedRange 与 CountableRange 这两个类型都遵循了 Sequence 协议,所以它们可以用于 for-in 循环迭代。

// 这里的stringRange是一个ClosedRange<String>类型,
// 表示该范围从"aaa"到"ccc"之间
let stringRange = "aaa" ... "ccc"
 
// 这里的charRange是一个Range<Character>类型,
// 表示该范围从"a"一直到"c",但不包括"c"
let charRange = Character("a") ..< Character("c")
 
// 这里的doubleRange是一个ClosedRange<Double>类型,
// 表示该范围从1.0到3.0之间
let doubleRange = 1.0 ... 3.0
 
// 这里的range是一个CountableRange<Int>类型,
// 表示该范围从1到5,但不包括5
let range = 1 ..< 5
 
// 我们来检验一下stringRange
switch "ccb" {
case stringRange:
// 结果输出:In stringRange!
print("In stringRange!")
default:
print("Not in stringRange!")
}
 
// 我们来检验一下charRange
switch Character("b") {
case charRange:
// 结果输出:In charRange!
print("In charRange!")
default:
print("Not in charRange!")
}
 
// 我们来检验一下doubleRange
switch 3.0 {
case doubleRange:
// 输出:In doubleRange!
print("In doubleRange!")
default:
print("Not in doubleRange!")
}
 
// 我们通过for-in循环依次输出range的值
for i in range {
print("\(i)")
}
 
let array = [1, 2, 3, 4, 5, 6, 7, 8]
 
// 我们用range范围来获取array的子数组,
// 这里取的就是array索引位置从1到4的元素,
// subArray的类型为:ArraySlice<Int>
let subArray = array[range]
 
// 输出subArray的元素:subArray: [2, 3, 4, 5]
print("subArray: \(subArray)")

像 ClosedRange、Range、 CountableClosedRange 以及 CountableRange 都具有以下实例方法与属性:
lowerBound:表示当前范围对象的下边界,一般都是范围操作符左操作数的值。
upperBound:表示当前对象的上边界。这里无论是闭区间还是半开区间,上边界的值一般都是范围操作符的右操作数的值。
isEmpty:表示当前范围是否为一个空范围,如果是空范围,那么该属性的值为 true,否则为 false。对于一个闭区间范围而言,它不会存在空范围,所以这个属性必定为 false。
contains(:):判断当前范围是否包含了指定的对象。
overlaps(
:):判断指定的范围是否与当前范围对象存在叠交,只要两者有交集,那么就返回 true,否则为 false。
clamped(to:):裁减当前的范围到指定的区间范围内。
我们下面举一些例子进行说明:

// doubleRange是一个ClosedRange<Double>类型的闭区间范围常量
let doubleRange = 1.0 ... 3.0
 
// 访问其下边界,值为1.0
print("lower bound: \(doubleRange.lowerBound)")
 
// 访问其上边界,值为3.0
print("upper bound: \(doubleRange.upperBound)")
 
// 判断doubleRange是否包含2.5,
// 结果为true
print("contains 2.5? \(doubleRange.contains(2.5))")
 
// 判断doubleRange与2.0 ... 5.0的范围是否有叠交,
// 结果为true
print("overlaps? \(doubleRange.overlaps(2.0 ... 5.0))")
 
// 判断doubleRange与3.0 ..< 4.0的范围是否有叠交,
// 结果为true
print("overlaps? \(doubleRange.overlaps(3.0 ..< 4.0))")
 
// 将doubleRange裁减到0.5 ... 1.8范围内,
// 然后将它赋值给subRange常量
let subRange = doubleRange.clamped(to: 0.5 ... 1.8)
 
// 这里输出:subRange = 1.0...1.8
print("subRange = \(subRange)")
 
// range是一个CountableRange<Int>类型的半开区间范围常量
let range = 1 ..< 5
 
// 访问其下边界,值为1
print("lower bound: \(range.lowerBound)")
 
// 访问其上边界,值为5
print("upper bound: \(range.upperBound)")
 
// 判断该范围是否包含5,结果为false
print("contains 5? \(range.contains(5))")
 
// 判断该范围是否与4 ... 6范围有叠交,
// 结果为true
print("overlaps? \(range.overlaps(4 ... 6))")
 
// 判断该范围是否与0 ..< 1范围有叠交,
// 结果为false
print("overlaps? \(range.overlaps(0 ..< 1))")
 
// 将range范围裁剪到5 ..< 6范围内,
// 然后赋值给clampedRange对象
let clampedRange = range.clamped(to: 5 ..< 6)
 
// clampedRange的范围为:5 ..< 5
print("clampedRange = \(clampedRange)")
 
// 这里可查询到,clampedRange是一个空范围
print("Is empty? \(clampedRange.isEmpty)")

单边范围操作符

Swift 引入了单边范围操作符,表示只对范围操作符的一端设置操作数,另一端缺省。它有三种类型—— a... 、...b、..<b 。其中,a... 形式的单边范围操作符的返回类型为 PartialRangeFrom,它是一个后缀单目操作符,表示从其操作数开始的范围,也就是说,如果有一个大于等于 a 的数,那么它肯定在此范围内。...b 的返回类型为 PartialRangeThrough,它是一个前缀单目操作符,表示以 b 作为终点的范围,也就是说,如果有一个小于等于 b 的数,那么它肯定在此范围内。..<b 返回 PartialRangeUpTo 类型,它也是一个前缀单目操作符,表示以 b 作为终点,但不包含 b 的范围,也就是说,如果有一个小于 b 的数,那么它肯定在此范围内。这里要注意的是,对于所有种类的单边范围操作符,其操作数必须紧贴该操作符,这就跟其他单目操作符的要求一样。
我们用单边范围操作符来获取一个数组的子数组以及一个字符串的子串的时候非常方便。比如,我们想获取从某一端开始一直到最后的子串,或者从开头一直到某一端结束的子串,我们就不需要计算整个串的长度或是计算起始索引位置。下面我们先举一些简单的例子。

/// 声明一个常量数组
let array = [1, 2, 3, 4, 5]
 
/// 取array从索引2到最后一个元素的子数组,
/// sub1的类型为ArraySlice<Int>
let sub1 = array[2...]
 
// 打印出:sub1 = [3, 4, 5]
print("sub1 = \(sub1)")
 
/// 取array从第一个元素到索引3元素的子数组
/// sub2的类型为ArraySlice<Int>
let sub2 = array[...3]
 
// 打印出:sub2 = [1, 2, 3, 4]
print("sub2 = \(sub2)")
 
/// 取array从第一个元素到索引2元素的子数组
/// sub3的类型为ArraySlice<Int>
let sub3 = array[..<3]
 
// 这里打印:sub3 = [1, 2, 3]
print("sub3 = \(sub3)")
 
if (...3).contains(3) {
// 由于3在 ...3 的范围内,
// 所以这里打印出contains
print("contains")
}
// 由于4不在 5... 的范围内,
// 所以这里不打印contains
if (5...).contains(4) {
print("contains")
}
 
// 由于5不在 ..<5 的范围内,
// 所以这里不打印contains
if (..<5).contains(5) {
print("contains")
}
 
由于单边范围操作符不能表示一个有限范围的值,因此它不可能遵循 Sequence 协议,从而我们不能将它们用在 for-in 语句中。

相关文章

  • 范围操作符 单边范围操作符

    在Swift编程语言中引入了范围操作符这种非常方便实用的操作符。范围操作符可用于 for-in 循环迭代、获取一个...

  • php 类中 :: 与 -> 符号的使用

    php 手册--范围解析操作符 (::) 范围解析操作符(也可称作 Paamayim Nekudotayim)或者...

  • php学习之操作符

    1. 范围解析操作符 (::) 范围解析操作符(也可称作 Paamayim Nekudotayim)或者更简单地说...

  • 100 Days of SwiftUI 03

    算术操作符 范围操作符 三元操作符 switch 输出 :晴天冰雹台风闪电 fallthrough 如果当前cas...

  • RxJava 学习进行中 -Range&GroupBy

    1.Range Range操作符发射一个范围内的有序整数序列,你可以指定范围的起始和长度。RxJava将这个操作符...

  • swift4.1 系统学习五 范围操作符

    简单的代码也要亲自实现看看。 //1. 范围操作符 这是一个新的概念,在swift中常常使用。1.闭区间范围操作符...

  • BI-SQL丨BETWEEN

    BETWEEN操作符 BETWEEN操作符属于WHERE语句的补充。通常与AND搭配使用,可以用来限定数据范围。 ...

  • 十四、SQL BETWEEN 操作符

    BETWEEN 操作符在 WHERE 子句中使用,作用是选取介于两个值之间的数据范围。 BETWEEN 操作符 操...

  • Perl 6 中的操作符(三)

    范围和范围迭代器语法 .. 范围操作符有各种在两端带有 ^符号的变体以表明把那个端点排除在范围之外。 它总会产生一...

  • RxJava学习(5.9)

    1.RxJava 操作符 just、from、defer、interval(间隔)、range(范围)、repea...

网友评论

      本文标题:范围操作符 单边范围操作符

      本文链接:https://www.haomeiwen.com/subject/ottznftx.html