AmosCloud

Library

Have a Question?

If you have any question you can ask below or enter what you are looking for!

Scala_04【控制结构】

主要内容

  • if else 表达式
  • while 表达式
  • for 表达式

学习目标

  • 熟练使用 if else
  • 熟练使用for循环

控制结构

1. if-else 表达式

  • Scala中提供与大部分编程语言中类似的if-else选择结构语句

  • 语法: if(expr) { expr为true时执行的语句 } else { expr为false时执行的语句 }

  • 例如:将a和b中较大值的平方赋值给max

val a = 22
val b = 66
var max = 0
if (a > b) {
  max = a * a
} else {
  max = b * b
}
// if或else分支只有一行代码时可以省略{}
if (a > b) max = a * a else max = b * b
// 由于scala中代码块或表达式都有返回值,上面的操作可以改写成
max = if (a > b) a * a else b * b // 类似C和Java中的三目运算符用法
  • 练习:
    写一个方法输入成绩grade:Int返回评级:85分以上A,75分以上B,60分以上C,60以下D

2. while和do-while表达式

  • while和do-while表达式固定返回Unit

2.1 while

  • while语法: while(expr){ expr为true时反复执行的语句 }

  • 例如: 打印50以内的斐波那契数列

var first = 0
var second = 1
var fibonacci = 0
while (fibonacci < 50) {
  println(fibonacci)
  first = second
  second = fibonacci
  fibonacci = first + second
}

2.2 do-while

  • do-while语法: do{ expr为true时反复执行的语句 } while (expr)

  • 例如:计算一个正整数的各位之和

var i = 53672
var sum = 0
do {
  sum += i % 10
  i /= 10
} while (i > 0)
println(sum) // 23

2.3 关于break

  • 需要注意的是Scala中没有提供break和continue的关键字

  • 如果要实现类似的功能,可以使用控制循环条件、函数封装+return或BreaksAPI

  • 例如:判断一个整数是否含有偶数位

    // 使用外部Boolean控制循环条件
    var i = 67253
    var nonEven = true
    while (nonEven) {
    if (i % 10 % 2 == 0) {
    println("包含偶数位")
    nonEven = false
    }
    i /= 10
    }
    // 使用函数封装和return关键字
    var i = 67253
    def checkEven(n: Int) {
    var tmp = n
    while (true) {
      if (tmp % 10 % 2 == 0) {
        println("包含偶数位")
        return
      }
      tmp /= 10
    }
    }
    checkEven(i)
    // 使用BreaksAPI
    Breaks.breakable {
    while (true) {
      if (i % 10 % 2 == 0) {
        println("包含偶数位")
        Breaks.break()
      }
      i /= 10
    }
    }
  • 练习:
    寻找大于n的第一个质数

3. for 推导式

3.1 概述

  • Scala提供了一个功能强大的序列推导式以for关键字开始。
  • 语法:for (enumerators) { 循环体 }
    • 枚举器(enumerators):指的是一组以分号分割的枚举器,枚举器可以由一个产生新变量的生成器(generator)以及一个守卫(guard)组成。
    • 生成器(generator):指的是一个形如变量名 <- 集合的表达式,生成器会在每次迭代时从<-右边的集合中取一个元素赋值给<-左边的变量。
    • 守卫(guard):指的是一个形如if expr的表达式,expr为true时执行循环体,为false时类似Java中的continue操作,跳过当此继续下一次循环。

3.2 与Java的foreach类似

  • Scala的for推导式使用时与Java的foreach极为相似,但功能更加强大

    • Java的foreach:
//for ( 类型 变量 : 集合 ) {
//  循环体;
//}
int[] arr = {1, 2, 3};
for (int i : arr) {
  System.out.print(i + " ");
}
// 1 2 3
  • Scala的for推导式
//for ( 元素 <- 集合 ) {
//  循环体;
//}
val ints = Array(1, 2, 3)
for (i <- ints) {
  print(i+" ")
}
// 1 2 3

3.3 守卫(guard)

  • 守卫可以实现对生成器生成的元素进行过滤,可以理解为提供类似Java中continue的功能。

  • 例如:打印10以3的倍数

for (i <- 1 to 10 if i % 3 == 0) {
  print(i+" ")
}
// 3 6 9

3.4 包含多个枚举器

  • for推导式允许同时包含多个枚举器,相当于for的嵌套,运行时会按照顺序在第一个枚举器取一次值时,执行完第二个枚举器的所有取值。

  • 例如:打印9x9乘法表

for (i <- 1 to 9; j <- 1 to i) {
  print(s"${i}x$j=${i * j}  ")
  if (i == j) println()
}

3.5 yield

  • 另一种for推导式语法为:for (enumerators) yield e

  • for-yield会将生成器中满足守卫条件的元素代入表达式e的运算,最终将所有的运算结果收集到集合并返回

  • 例如: 获取字符串中所有字符的ASCII值

val str = "abc"
val ints = for (c <- str) yield c.asInstanceOf[Int]
println(ints)