循环与范围
for
关键字用于对序列中的每个值执行一系列代码块。
值的集合可以是整数范围、String
,或者在本书后面将会介绍的项目集合。in
关键字表示你正在遍历值:
for (v in values) {
// 使用 v 做一些操作
}
每次循环迭代,v
都会被赋予 values
中的下一个元素。
下面是一个 for
循环,重复一个动作固定次数:
// LoopingAndRanges/RepeatThreeTimes.kt
fun main() {
for (i in 1..3) {
println("Hey $i!")
}
}
/* 输出:
Hey 1!
Hey 2!
Hey 3!
*/
输出显示索引 i
接收了范围从 1 到 3 的每个值。
范围是由一对端点定义的值间隔。有两种基本方法来定义范围:
// LoopingAndRanges/DefiningRanges.kt
fun main() {
val range1 = 1..10 // [1]
val range2 = 0 until 10 // [2]
println(range1)
println(range2)
}
/* 输出:
1..10
0..9
*/
- [1] 使用
..
语法会将两个边界都包含在结果范围内。 - [2]
until
排除了结束点。输出显示10
不是范围的一部分。
显示范围会生成可读性良好的格式。
下面的代码将从 10 到 100 的数字求和:
// LoopingAndRanges/SumUsingRange.kt
fun main() {
var sum = 0
for (n in 10..100) {
sum += n
}
println("sum = $sum")
}
/* 输出:
sum = 5005
*/
你可以以相反的顺序遍历范围。你还可以使用 step
值来改变默认的间隔值 1
:
// LoopingAndRanges/ForWithRanges.kt
fun showRange(r: IntProgression) {
for (i in r) {
print("$i ")
}
print(" // $r")
println()
}
fun main() {
showRange(1..5)
showRange(0 until 5)
showRange(5 downTo 1) // [1]
showRange(0..9 step 2) // [2]
showRange(0 until 10 step 3) // [3]
showRange(9 downTo 2 step 3)
}
/* 输出:
1 2 3 4 5 // 1..5
0 1 2 3 4 // 0..4
5 4 3 2 1 // 5 downTo 1 step 1
0 2 4 6 8 // 0..8 step 2
0 3 6 9 // 0..9 step 3
9 6 3 // 9 downTo 3 step 3
*/
- [1]
downTo
生成递减范围。 - [2]
step
改变了间隔。在这里,范围的步长为 2,而不是默认的 1。 - [3]
until
也可以与step
一起使用。注意这如何影响输出。
在每种情况下,数字序列形成一个等差数列。showRange()
接受一个 IntProgression
参数,这是一种内置类型,包括了 Int
范围。注意,每行输出的注释中出现的 IntProgression
的 String
表示形式通常与传递给 showRange()
的范围不同 - IntProgression
将输入转化为一个等效的常见形式。
你还可以生成一个字符范围。以下 for
循环从 a
遍历到 z
:
// LoopingAndRanges/ForWithCharRange.kt
fun main() {
for (c in 'a'..'z') {
print(c)
}
}
/* 输出:
abcdefghijklmnopqrstuvwxyz
*/
你可以遍历整数和字符等整数量的元素范围,但不能遍历浮点数值。
使用方括号可以通过索引访问字符。因为在 String
中我们从零开始计算字符,所以 s[0]
会选择 String s
的第一个字符。选择 s.lastIndex
会产生最后一个索引号:
// LoopingAndRanges/IndexIntoString.kt
fun main() {
val s = "abc"
for (i in 0..s.lastIndex) {
print(s[i] + 1)
}
}
/* 输出:
bcd
*/
有时候人们将 s[0]
描述为“第零个字符”。
字符存储为与其 ASCII 代码 对应的数字,因此将整数添加到字符会产生一个新的字符,其对应新的代码值:
// LoopingAndRanges/AddingIntToChar.kt
fun main() {
val ch: Char = 'a'
println(ch + 25)
println(ch < 'z')
}
/* 输出:
z
true
*/
第二个 println()
显示你可以比较字符代码。
for
循环可以直接遍历 String
:
// LoopingAndRanges/IterateOverString.kt
fun main() {
for (ch in "Jnskhm ") {
print(ch + 1)
}
}
/* 输出:
Kotlin!
*/
ch
依次接收每个字符。
在下面的示例中,函数 hasChar()
遍历字符串 s
并测试它是否包含给定的字符 ch
。在函数中间的 return
在答案找到时停止函数:
// LoopingAndRanges/HasChar.kt
fun hasChar(s: String, ch: Char): Boolean {
for (c in s) {
if (c == ch) return true
}
return false
}
fun main() {
println(hasChar("kotlin", 't'))
println(hasChar("kotlin", 'a'))
}
/* 输出:
true
false
*/
下一部分将展示 hasChar()
是不必要的,你可以使用内置的语法来替代。
如果你只是想要重复一个动作固定次数,可以使用 repeat()
替代 for
循环:
// LoopingAndRanges/RepeatHi.kt
fun main() {
repeat(2) {
println("hi!")
}
}
/* 输出:
hi!
hi!
*/
repeat()
是标准库函数,不是关键字。你将在本书后面看到它是如何被创建的。
练习和解答可在 www.AtomicKotlin.com 找到。