Scala实验二——3.统计学生成绩

学生的成绩清单格式如下所示,第一行为表头,各字段意思分别为学号、性别、课程名
1、课程名 2 等,后面每一行代表一个学生的信息,各字段之间用空白符隔开
Id gender Math English Physics
301610 male 80 64 78
301611 female 65 87 58
...
给定任何一个如上格式的清单(不同清单里课程数量可能不一样),要求尽可能采用函
数式编程,统计出各门课程的平均成绩,最低成绩,和最高成绩;另外还需按男女同学分开,
分别统计各门课程的平均成绩,最低成绩,和最高成绩。
测试样例 1 如下:
Id gender Math English Physics
301610 male 80 64 78
301611 female 65 87 58
301612 female 44 71 77
301613 female 66 71 91
301614 female 70 71 100
301615 male 72 77 72
301616 female 73 81 75
301617 female 69 77 75
301618 male 73 61 65
301619 male 74 69 68
301620 male 76 62 76
301621 male 73 69 91
301622 male 55 69 61
301623 male 50 58 75
301624 female 63 83 93
301625 male 72 54 100
301626 male 76 66 73
301627 male 82 87 79
301628 female 62 80 54
301629 male 89 77 72
运行结果:
 
源代码:(摘自网络)
object scoreReport
{
  def main(args:Array[String])
  {
    //假设数据在当前目录下
    val inputFile=scala.io.Source.fromFile("test2-3.txt")

    //"\s"是字符串正则表达式,将每行按空白字符(包括空格/制表符)分开
    //由于可能涉及多次遍历,通过toList将Itertor装为List
    //originalData的类型为List[Array[String]]
    val originalData=inputFile.getLines.map{_.split{"\s+"}}.toList

    val courseNames=originalData.head.drop(2) //获取第一行中的课程名
    val allStudents=originalData.tail //去除第一行剩下的数据
    val courseNum=courseNames.length


    def statistc(lines:List[Array[String]])=
    {
      //for推导式,对每门课程生成一个三元组,分别表示总分,最低分和最高分
      (for(i<- 2 to courseNum+1) yield
        {
          //取出需要统计的列
          val temp =lines map
            {
              elem=>elem(i).toDouble
            }
          (temp.sum,temp.min,temp.max)
        })map{case(total,min,max)=>(total/lines.length,min,max)} //最后一个map对for的结果进行修改,将总分转为平均分
    }

    //输出结果函数
    def printResult(theresult:Seq[(Double,Double,Double)])
    {
      //遍历前调用zip方法将课程名容器和结果容器合并,合并结果为二元组容器
      (courseNames zip theresult)foreach
        {
          case(course,result)=>
            println(f"${course+":"}%-10s${result._1}%5.2f${result._2}%8.2f${result._3}%8.2f")
        }
    }

    //分别调用两个函数统计全体学生并输出结果
    val allResult=statistc(allStudents)
    println("course    average    min    max")
    printResult(allResult)

    //按性别划分为两个容器
    val (maleLines,femaleLines)=allStudents partition
      {
        _(1)=="male"
      }

    //分别调用两个函数统计男学生并输出结果
    val maleResult=statistc(maleLines)
    println("course    average    min    max")
    printResult(maleResult)

    //分别调用两个函数统计女学生并输出结果
    val femaleResult=statistc(femaleLines)
    println("course    average    min    max")
    printResult(femaleResult)

  }

}
View Code
涉及知识点:

Scala List(列表):List的特征是其元素以线性方式存储,集合中可以存放重复对象;

Scala Set(集合):Set是最简单的一种集合。集合中的对象不按特定的方式排序,并且没有重复对象;

Scala Map(映射):Map 是一种把键对象和值对象映射的集合,它的每一个元素都包含一对键对象和值对象;

Scala 元组:元组是不同类型的值的集合

object Test {
   def main(args: Array[String]) {
      val t = (4,3,2,1)

      val sum = t._1 + t._2 + t._3 + t._4

      println( "元素之和为: "  + sum )
   }
}

执行以上代码,输出结果为:

元素之和为: 10
 Scala Option:Option[T] 表示有可能包含值的容器,也可能不包含值
// 虽然 Scala 可以不定义变量的类型,不过为了清楚些,还是把他显示的定义上了
 
val myMap: Map[String, String] = Map("key1" -> "value")
val value1: Option[String] = myMap.get("key1")
val value2: Option[String] = myMap.get("key2")
 
println(value1) // Some("value1")
println(value2) // None

 2.Scala 正则表达式

正则表达式(regular expression)描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。

3.for循环与yield

for循环中的 yield 会把当前的元素记下来,保存在集合中,循环结束后将返回该集合。Scala中for循环是有返回值的。如果被循环的是Map,返回的就是Map,被循环的是List,返回的就是List,以此类推。

例:

1 scala> for (i <- 1 to 5) yield i
2 res10: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3, 4, 5)

tountil 的用法(不带步长,带步长区别)

 /**

     * to和until

     * 例:

     * 1 to 10 返回1到10的Range数组,包含10

     * 1 until 10 返回1到10 Range数组 ,不包含10

     */

    

    println(1 to 10 )//打印 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

    println(1.to(10))//与上面等价,打印 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

    

    println(1 to (10 ,2))//步长为2,从1开始打印 ,1,3,5,7,9

    println(1.to(10, 2))

    

    println(1 until 10 ) //不包含最后一个数,打印 1,2,3,4,5,6,7,8,9

    println(1.until(10))//与上面等价

    

println(1 until (10 ,3 ))//步长为2,从1开始打印,打印1,4,7

创建for循环

    for( i <- 1 to 10 ){

      println(i)

    }

for循环中可以加条件判断,可以使用分号隔开,也可以不使用分号

 //可以在for循环中加入条件判断

    for(i<- 1 to 10 ;if (i%2) == 0 ;if (i == 4) ){

      println(i)

}

scala中不能使用count++count只能使用count = count+1 count += 1

for循环用yield 关键字返回一个集合

while循环,while(){}do {}while()

//将for中的符合条件的元素通过yield关键字返回成一个集合

    val list = for(i <- 1 to 10  ; if(i > 5 )) yield i 

    for( w <- list ){

      println(w)

}

 

   /**

     * while 循环

     */

    var index = 0 

    while(index < 100 ){

     println("第"+index+"次while 循环")

      index += 1 

    }

    index = 0 

    do{

     index +=1 

     println("第"+index+"次do while 循环")

}while(index <100 )
原文地址:https://www.cnblogs.com/sengzhao666/p/12254824.html