天天看点

Scala之for循环

Scala没有与for()循环直接对应的结构。如果你需要这样的循环,有两个选择:一是使用while循环,而是使用如下for语句:

for (i <- 1 to n)
  r = r * i
           

说明:1 to n 这个调用返回数字1到数字n的Range(区间)。

to,until都表示范围,二者有何区别?

to为包含上限的闭区间,如:1 to 3,Range为1,2,3;

until不包含上限,如:1 to 3, Range为1,2

在需要使用从0到n-1的区间时,可以使用until方法。

语法结构for (i <- 表达式)让变量i遍历<-右边的表达式的所有值。至于这个遍历具体如何执行,则取决于表达式的类型。对于Scala集合比如Range而言,这个循环会让i依次取得区间中的每个值。

说明:在for循环的变量之前并没有val或var的指定。该变量的类型是集合的元素类型。循环变量的作用域一直持续到循环结束。

在Scala中,对循环的使用并不如其他语言那么频繁。通常我们可以通过对序列中的所有值应用某个函数的方式来处理它们,而完成这项工作只需要一次方法调用即可。

说明:Scala并没有提供break或continue语句来退出循环。那么如果需要break时我们该怎么做呢,有如下几个选择:

1、使用Boolean型的控制变量;

2、使用嵌套函数--你可以从函数当中return;

  3、使用Breaks对象中的break方法:

import scala.util.control.Breaks._
breakable {
  for (...) {
    if (...) break; //退出breakable块
    ...
  }
}
           

在这里,控制权的转移是通过抛出和捕获异常完成的,因此,如果时间很重要的话,应该尽量避免使用这套机制。

高级for循环和for推导式

Scala中的for循环比起Java和C++功能要丰富的多。

1、可以以变量<-表达式的形式提供多个生成器,用分号将它们隔开。如:

for(i <- 1 to 3; j <- 1 to 3) {
    print((10 * i + j) + " ");
  }

outputs: 11 12 13 21 22 23 31 32 33 
           

2、每个生成器都可以带一个守卫,以if开头的Boolean表达式:

for(i <- 1 to 3; j <- 1 to 3 <span style="color:#ff0000;">if i != j</span>) {
    print((10 * i + j) + " ");
  }

outputs: 12 13 21 23 31 32
           

注意 在if之前并没有分号。

3、可以使用任意多的定义,引入可以在循环中使用的变量:

for(i <- 1 to 3; from = 4 - i; j <- from to 3) {
    print((10 * i + j) + " ");
  }

outputs: 13 22 23 31 32 33
           

4、如果for循环的循环体以yield开始,则该循环会构造出一个集合,每次迭代生成集合中的一个值:

<span style="font-size:18px;">for(i <- 1 to 10) yield {
      var r = i % 3
      print(r + " ")
  }

//生成 Vector(1, 2, 0, 1, 2, 0, 1, 2, 0, 1)
outputs: 1 2 0 1 2 0 1 2 0 1</span>
           

这类循环叫做for推导式。

for推导式生成的集合与它的第一个生成器是类型兼容的。

for (c <- "Hello"; i <- 0 to 1) yield {
    var v = (c + i).toChar;
    print(v);
  }

outputs: HIeflmlmop
           

说明:如果你愿意,你也可以将生成器、守卫和定义包含在花括号中,并可以以换行的方式而不是分号来隔开它们:

for{i <- 1 to 3
      from = 4 - i
      j <- from to 3 
    }
  print((10 * i + j) + " ")

outputs: 13 22 23 31 32 33
           

参考书籍:《快学Scala》