在 Scala 中,多重循环(嵌套循环)可以通过简洁的语法实现,无需像其他语言那样显式嵌套大括号,而是通过在 for 推导式中用逗号分隔多个迭代变量来表示。这种语法让代码更紧凑,同时支持条件过滤(守卫)和结果收集(yield)。
1. 基础多重循环:嵌套迭代
最常见的场景是遍历多个集合的笛卡尔积,例如双层循环遍历行和列。
示例:打印 3x3 的矩阵索引
// 外层循环:i 从1到3(行)
// 内层循环:j 从1到3(列)
for (i <- 1 to 3; j <- 1 to 3) {
println(s"($i, $j)")
}
输出:
(1, 1)
(1, 2)
(1, 3)
(2, 1)
(2, 2)
(2, 3)
(3, 1)
(3, 2)
(3, 3)
等价于传统嵌套循环的写法:
for (i <- 1 to 3) {
for (j <- 1 to 3) {
println(s"($i, $j)")
}
}
2. 带条件过滤(守卫)的多重循环
可以在多重循环中加入 if 条件,筛选符合要求的组合,避免不必要的迭代。
示例:打印两数之和为 5 的组合(i 从 1 到 4,j 从 1 到 4)
for (
i <- 1 to 4;
j <- 1 to 4;
if i + j == 5 // 守卫条件:两数之和为5
) {
println(s"$i + $j = 5")
}
输出:
1 + 4 = 5
2 + 3 = 5
3 + 2 = 5
4 + 1 = 5
3. 多重循环中使用 yield 收集结果
通过 yield 可以将多重循环的结果收集为一个新集合,避免手动创建集合并添加元素。
示例:生成 1-3 中两数乘积大于 3 的所有组合及其乘积
val results = for (
i <- 1 to 3;
j <- 1 to 3;
if i * j > 3 // 筛选乘积大于3的组合
) yield (i, j, i * j) // 收集 (i, j, 乘积) 元组
println(results)
输出:
Vector((2,2,4), (2,3,6), (3,2,6), (3,3,9))
4. 多重循环的控制:提前终止(break)
Scala 没有内置的 break 关键字,但可以通过 scala.util.control.Breaks 工具类实现循环终止。
示例:找到第一个和为 6 的组合后终止循环
import scala.util.control.Breaks._
breakable { // 包裹需要中断的代码块
for (i <- 1 to 5; j <- 1 to 5) {
println(s"检查 ($i, $j)")
if (i + j == 6) {
println(s"找到目标:$i + $j = 6")
break() // 终止循环
}
}
}
输出:
检查 (1, 1)
检查 (1, 2)
检查 (1, 3)
检查 (1, 4)
检查 (1, 5)
检查 (2, 1)
找到目标:2 + 4 = 6 // 找到后立即终止
5. 实际应用:打印九九乘法表
多重循环的经典案例,外层控制行数,内层控制每行的列数(列数 ≤ 行数)。
for (i <- 1 to 9; j <- 1 to i) { // j 从1到i,确保每行不超过行数
print(s"$j×$i=${i*j}\t") // \t 制表符对齐
if (j == i) println() // 每行结束后换行
}
输出:
1×1=1
1×2=2 2×2=4
1×3=3 2×3=6 3×3=9
... ... ...
1×9=9 2×9=18 ... 9×9=81
总结
- Scala 多重循环通过
for (变量1 <- 集合1; 变量2 <- 集合2; ...)实现,语法简洁。 - 支持添加多个
if守卫条件,灵活筛选迭代结果。 - 用
yield可直接收集循环结果为集合(如Vector、List等)。 - 如需提前终止循环,需借助
Breaks工具类的breakable和break方法。