范围代表的是两个值的区间,它由上下边界进行定义。你可以通过 ..< 来创建一个不包含上边界的半开范围,或者使用 ... 创建同时包含上下边界的闭合范围:
let singleDigitNumbers = 0..<10
Array(singleDigitNumbers)
let lowercaseLetters = Character("a")...Character("z")
半开范围和闭合范围各有所用:
- 只有半开范围能表达空间隔 (也就是下界和上界相等的情况,比如 5..<5)。
- 只有闭合范围能包括其元素类型所能表达的最大值 (比如 0...Int.max)。而半开范围则要求范围上界是一个比自身所包含的最大值还要大 1 的值。
可数范围
范围看起来很自然地会是一个序列或者集合类型,但是可能出乎你的意料,Range 和 ClosedRange 既非序列,也不是集合类型。有一部分范围确实是序列,不然的话,我们就不能实现在 for 循环中对于一个整数范围进行迭代了:
for i in 0..<10 {
print("\(i)", terminator: " "))
}
之所以能这样做的原因,是因为 0..<10 的类型其实是一个 CountableRange<Int>。CountableRange 和 Range 很相似,只不过它还需要一个附加约束:它的元素类型需要遵守 Strideable 协议 (以整数为步长)。Swift 将这类功能更强的范围叫做可数范围,这是因为只有这类范围可以被迭代。可数范围的边界可以是整数或者指针类型,但不能是浮点数类型,这是由于 Stride 类型中有一个整数的约束。如果你想要对连续的浮点数值进行迭代的话,你可以通过使用 stride(from:to:by) 和 stride(from:through:by) 方法来创建序列用以迭代。Strideable 的约束使得 CountableRange 和 CountableClosedRange 遵守 RandomAccessCollection,于是我们就能够对它们进行迭代了。
部分范围
部分范围 (partial range) 指的是将 ... 或 ..< 作为前置或者后置运算符来使用时所构造的范围。比如,0... 表示一个从 0 开始的范围。这类范围由于缺少一侧的边界,因此被称为部分范围。具体来说,有四种不同的部分范围:
let fromA: PartialRangeFrom<Character> = Character("a")...
let throughZ: PartialRangeThrough<Character> = ...Character("z")
let upto10: PartialRangeUpTo<Int> = ..<10
let fromFive: CountablePartialRangeFrom<Int> = 5...
其中能够计数的只有 CountablePartialRangeFrom 这一种类型,四种部分范围类型中,只有它能被进行迭代。迭代操作会从 lowerBound 开始,不断重复地调用 advanced(by: 1)。如果你在一个 for 循环中使用这种范围,你必须牢记要为循环添加一个 break 的退出条件,否则循环将无限进行下去 (或者当计数溢出的时候发生崩溃)。PartialRangeFrom 不能被迭代,这是因为它的 Bound 不满足 Strideable。而 PartialRangeThrough 和 PartialRangeUpTo 则是因为没有下界而无法开始迭代。
网友评论