Ranges

range 表达式拥有 rangeTo 函数操作符是 .. 。 Range 可以对任何可比较的类型做操作,但对很多原语是优化过的。下面是些例子:

if (i in1..10) {
    println(i)
}

if (x !in1.0..3.0) println(x)

if (str in"island".."isle") println(str)

数字的范围有个附加的特性:它们可以迭代。编译器会把它转成类似于 java 的 for 循环的形式,且不用担心越界:

for (i in1..4) print(i) for (i in4..1) print(i) for (x in1.0..2.0) print("$x ") 

如果你想迭代数字并想反过来,这个相当简单,你可以使用 downTo() 函数

for (i in4 downTo 1) print(i)

也可以使用指定步数的迭代,这个用到 step()

for (i in1..4 step 2) print(i) for (i in4 downTo 1 step 2) print(i) for (i in1.0..2.0 step 0.3) print("$i ") 

工作原理

在标准库中有俩种接口:Range 和 Progression

Range 表示数学范围上的一个间隔。它有俩个端点:start 和 end 。主要的操作符是 contains 通常在 in/!in 操作符内:

Progression 表示一个算数级数。它有一个 start 和 end 以及一个非零 increment 。Progression 是Iterable 的一个子类,因此可以使用在 for 循环中,或者 map filter 等等。第一个元素是 start 下一个元素都是前一个元素的 increment 。Progression 的迭代与 java/javaScript 的 for 循环相同:

for (int i = start; i <= end; i += increment) {
  // ...
}
// if increment < 0
for (int i = start; i >= end; i += increment) {
  
}

范围指标

使用例子:

if (i in1..10) println(i)

if (x in1.0..3.0) println(x)

if (str in"island".."isle") println(str)

for (i in1..4) print(i) for (i in4..1) print(i) for (i in4 downTo 1) print(i) for (i in1..4 step 2) print(i) for (i in (1..4).reversed()) print(i) for (i in (1..4).reversed() step 2) print(i) for (i in4 downTo 1 step 2) print(i) for (x in1.0..2.0) print("$x ") for (x in1.0..2.0 step 0.3) print("$x ") for (x in2.0 downTo 1.0 step 0.3) print("$x ") for (str in"island".."isle") println(str) 

常见的接口的定义

有俩种基本接口:RangeProgression

Range 接口定义了一个范围,或者是数学意义上的一个间隔。

interface Range<T : Comparable<T>> {
    val start: T
    val end: T
    funcontains(Element : T): Boolean
}

Progression 定义了数学上的级数。包括 start end increment 端点。最大的特点就是它可以迭代,因此它是 Iterable 的子类。end 不是必须的。

interface Progression<N : Number> : Iterable<N> {
    val start : N
    val end : N
    val increment : Number
}

与 java 的 for 循环类似:

for (int i = start; i <= end; i += increment) {
  // ...
}

// if increment < 0
for (int i = start; i >= end; i += increment) {
  
}

类的实现

为避免不需要的重复,让我们先考虑一个数字类型 Int 。其它的数字类型也一样。注意这些类的实例需要用相应的构造函数来创建,使用 rangeTo() downTo() reversed() stop() 实用函数。

IntProgression 类很直接也很简单:

classIntProgression(overrideval start: Int, overrideval end: Int, overrideval increment: Int ): Progression<Int> {
    overridefuniterator(): Iterator<Int> = IntProgressionIteratorImpl(start, end, increment)
}

IntRange 有些狡猾:它实现了 Progression<Int>Range<Int> 接口,因为它天生以通过 range 迭代(默认增加值是 1 ):

classIntRange(overrideval start: Int, overrideval end: Int): Range<Int>, Progression<Int> {
  overrideval increment: Intget() = 1overridefuncontains(element: Int): Boolean = start <= element && element <= end
  override fun iterator(): Iterator<Int> = IntProgressionIteratorImpl(start, end, increment)
}

ComparableRange 也很简单:

classComparableRange<T : Comparable<T>>(overrideval start: T, overrideval end: T): Range<T> {
  overridefuncontains(element: T): Boolean = start <= element && element <= end
}

一些实用的函数

rangeTo()

rangeTo() 函数仅仅是调用 *Range 的构造函数,比如:

classInt{
    funrangeTo(other: Byte): IntRange = IntRange(this, Other)funrangeTo(other: Int): IntRange = IntRange(this, other)
}

downTo()

downTo() 扩展函数可以为任何数字类型定义,这里有俩个例子:

funLong.downTo(other: Double): DoubleProgression {return DoubleProgression(this, other, -1.0)
}

funByte.downTo(other: Int): IntProgression {return IntProgression(this, other, -1)
}

reversed()

reversed() 扩展函数是给所有的 *Range*Progression 类定义的,并且它们都返回反向的级数。

fun IntProgression.reversed(): IntProgression {return IntProgression(end, start, -increment)
}

fun IntRange.reversed(): IntProgression {return IntProgression(end, start, -1)
}

step()

step() 扩展函数是给所有的 *Range*Progression 类定义的,所有的返回级数都修改了 setp 值。注意 step 值总是正的,否则函数不会改变迭代的方向。

fun IntProgression.step(step: Int): IntProgression {if (step <= 0) throw IllegalArgumentException("Step must be positive, was: $step")
  return IntProgression(start, end, if (increment >0) step else -step)
}

fun IntRange.step(step: Int): IntProgression {if (step <= 0) throw IllegalArgumentException("Step must be positive, was: $step")
  return IntProgression(start, end, step)
}

本文转载自:https://huanglizhuo.gitbooks.io/kotlin-in-chinese/content/Other/Ranges.html