scala语法 - 高级for循环:循环守卫、多表达式、yield关键字

版权声明:本文为博主原创文章,转载联系 [email protected] https://blog.csdn.net/qq_31573519/article/details/82749188

1. 以符号 <- 提供生成器

// 基础用法
for (i <- 1 to 3) {
  println(i)
}
RS:
1
2
3

2. 可以提供多个生成器,并以分号分隔

// 以 <- 变量表达式的形式,提供多个for循环,以;隔开
for (i <- 1 to 3; j <-1 to 3) {
  println(s"i=$i, j=$j, i+j=${i + j}")
}

println("*****")

//
for (i <- 1 to 3; j <-1 to 2) {
  println(s"i=$i, j=$j, i+j=${i + j}")
}

RS:
i=1, j=1, i+j=2
i=1, j=2, i+j=3
i=1, j=3, i+j=4
i=2, j=1, i+j=3
i=2, j=2, i+j=4
i=2, j=3, i+j=5
i=3, j=1, i+j=4
i=3, j=2, i+j=5
i=3, j=3, i+j=6
*****
i=1, j=1, i+j=2
i=1, j=2, i+j=3
i=2, j=1, i+j=3
i=2, j=2, i+j=4
i=3, j=1, i+j=4
i=3, j=2, i+j=5

3. 控制守卫

所谓控制守卫,即一个以if开头的Boolean表达式

// 每个生成器可以带上 "守卫",以 if 开头的 Boolean表达式
for (i <- 1 to 3; j <-1 to 3 if i > j) {
  println(s"i=$i, j=$j, i+j=${i + j}")
}

RS:
i=2, j=1, i+j=3
i=3, j=1, i+j=4
i=3, j=2, i+j=5

注意:if前面没有分号

4. 可以引入任意多的定义,并也可以再引入再循环中使用的变量

// 可以引入任意多的定义,并也可以再引入再循环中使用的变量
for (i <- 1 to 3; from = 5 - i; j <- from to 3){
  println(s"i=$i, from=$from, j=$j")
}

RS:
i=2, from=3, j=3
i=3, from=2, j=2
i=3, from=2, j=3

在上例中,引入变量from。第一次,i=1,那么 from = 5-1=4,j<-4 to 3,这里4 to 3不满足定义了,直接跳出,进入第二次。第二次,i=2, from=5-2=3, j<- 3 to 3, 那么就是3。后面依次类推

5. 循环体 yield

先来看看几个Demo

// 循环体以yield开始
val a = for (i <- 1 to 10) yield i
print("a: "); println(a)

val aa = for (i <- "hello") yield i
print("aa: "); println(aa)

val b = for (i <- "hello"; j <- 1 to 3) yield (i + j)
print("b: "); println(b)

val ab = for (j <- 1 to 3; i <- "hello") yield (i + j)
print("ab: "); println(ab)

val c = for (i <- Map("A"->1,"b"->2)) yield i
print("c: "); println(c)

打印结果:
a: Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
aa: hello
b: Vector(105, 106, 107, 102, 103, 104, 109, 110, 111, 109, 110, 111, 112, 113, 114)
ab: Vector(105, 102, 109, 109, 112, 106, 103, 110, 110, 113, 107, 104, 111, 111, 114)
c: Map(A -> 1, b -> 2)

在《Programming Scala》中是这么定义yield关键字的:

For each iteration of your for loop, yield generates a value which will be remembered. It’s like the for loop has a buffer you can’t see, and for each iteration of your for loop, another item is added to that buffer. When your for loop finishes running, it will return this collection of all the yielded values. The type of the collection that is returned is the same type that you were iterating over, so a Map yields a Map, a List yields a List, and so on.

Also, note that the initial collection is not changed; the for/yield construct creates a new collection according to the algorithm you specify.

也就是说:

  1. 每次for循环,yield会生成一个缓冲变量,当循环结束的时候,这些缓存在buffer中的变量将会合并返回
  2. 返回的变量的类型与循环表达式中的类型一致

但是仔细观察上面几个Demo,不难发现在第二个特性中,返回值的类型是与第一个表达式的变量是一致的

猜你喜欢

转载自blog.csdn.net/qq_31573519/article/details/82749188