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 )

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM