Scala练习题+答案

本文提供了一组Scala练习题,涉及学生信息、分数和科目数据的读取、处理和统计分析。练习内容包括统计班级人数、学生总分、年级排名、总分超过年级平均分的学生、每科及格学生以及偏科严重的学生等。通过Scala代码实现这些统计功能,展示了数据处理和分析的能力。
摘要由CSDN通过智能技术生成

Scala练习题

数据

Scala练习题的数据可以通过URL链接下载,均是免费!

然后再项目中新建一个data目录,将数据放在data目录下

  • 学生信息表(data/students.txt):https://download.csdn.net/download/holiday0520/86268311
  • 学生分数表(data/score.txt):https://download.csdn.net/download/holiday0520/86268316
  • 学生科目表(data/subject.txt):https://download.csdn.net/download/holiday0520/86268317
依赖

pom.xml文件需要导入的依赖

<dependencies>
 <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>
        
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>2.11.12</version>
        </dependency>

        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-compiler</artifactId>
            <version>2.11.12</version>
        </dependency>

        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-reflect</artifactId>
            <version>2.11.12</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- Scala Compiler -->
            <plugin>
                <groupId>org.scala-tools</groupId>
                <artifactId>maven-scala-plugin</artifactId>
                <version>2.15.2</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
练习题目

练习1:

1、统计班级人数 [班级,人数]

2、统计学生的总分 [学号,姓名,年龄,总分]

练习2:
1、统计年级排名前十学生各科的分数 [学号,姓名,班级,科目,分数]

2、统计总分大于年级平均分的学生 [学号,姓名,班级,总分]

3、统计每科都及格的学生 [学号,姓名,班级,科目,分数]

4、统计每个班级的前三名 [学号,姓名,班级,分数]

5、统计偏科最严重的前100名学生 [学号,姓名,班级,科目,分数]

答案
import org.junit.{Before, Test}
import scala.io.{BufferedSource, Source}

class Demo_StudentExam {
  var students: List[Stu] = _
  var scores: List[Sco] = _
  var subjects: List[Sub] = _

  //接收一个由学生id构成的List,借助Map结构关联Stu学生数据及Sub学科数据,最终输出:[学号,姓名,班级,科目,分数]
  def filterWithIdsAndPrint(ids: List[String]): Unit = {
    //将学生和学科数据变成Map的形式
    val stuMap: Map[String, String] = students
      .map(stu => (stu.id, stu.name + "," + stu.clazz)).toMap

    val subMap: Map[String, String] = subjects
      .map(sub => (sub.subId, sub.subName)).toMap

    scores
      //从scores中根据传入的一批ids对数据进行过滤
      .filter(sco => ids.contains(sco.id))
      .map(sco => {
        val id: String = sco.id
        val subId: String = sco.subId
        val nameClazz: String = stuMap.getOrElse(id, "anonymous,")
        val subName = subMap.getOrElse(subId, "")
        s"$id,$nameClazz,$subName,${sco.score}"
      }).foreach(println)

  }

  @Before
  //加载三份数据,进行初始化
  def readFile(): Unit = {
    //加载学生数据
    val stuBS: BufferedSource = Source
      .fromFile("data/students.txt")

    //加载分数数据
    val scoBS: BufferedSource = Source
      .fromFile("data/score.txt")

    //加载学科数据
    val subBS: BufferedSource = Source
      .fromFile("data/subject.txt")

    students = stuBS
      .getLines()
      .toList
      .map(line => {
        //对数据进行切分并构建Stu对象
        val splits: Array[String] = line.split(",")
        val id: String = splits(0)
        val name: String = splits(1)
        val age: Int = splits(2).toInt
        val gender: String = splits(3)
        val clazz: String = splits(4)
        Stu(id, name, age, gender, clazz)
      })

    scores = scoBS
      .getLines()
      .toList
      .map(line => {
        //对数据进行切分并构建Sco对象
        val splits: Array[String] = line.split(",")
        val id: String = splits(0)
        val subId: String = splits(1)
        val score: Int = splits(2).toInt
        Sco(id, subId, score)
      })

    subjects = subBS
      .getLines()
      .toList
      .map(line => {
        //对数据进行切分并构建Sub对象
        val splits: Array[String] = line.split(",")
        val subId: String = splits(0)
        val subName: String = splits(1)
        val subScore: Int = splits(2).toInt
        Sub(subId, subName, subScore)
      })

    //关闭BS
    stuBS.close()
    scoBS.close()
    subBS.close()
  }

  @Test
  //测试
  def printData(): Unit = {
    students.take(10).foreach(println)
    scores.take(10).foreach(println)
    subjects.take(10).foreach(println)
  }

  @Test
  //练习1:
  //1.统计班级人数 [班级,人数]
  def clazzCnt(): Unit = {
    students
      .map(_.clazz)
      .groupBy(clazz => clazz)
      .map(kv => s"${kv._1},${kv._2.size}")
      .foreach(println)
  }

  @Test
  //2.统计学生的总分 [学号,姓名,年龄,总分]
  //通过Map进行关联
  def stuSumScore(): Unit = {
    //计算每个学生的总分
    val sumScoreMap: Map[String, Int] = scores
      .groupBy(sco => sco.id)
      .map(kv => {
        val id: String = kv._1
        val scoS: List[Sco] = kv._2
        //将每个学生的6门科目成绩分数score取出并求和
        val sumScore: Int = scoS.map(_.score).sum
        //以二元组形式返回,最终map逻辑处理完以后会得到一个Map
        (id, sumScore)
      })

    //遍历学生数据,通过学生id在sumScoreMap中,获取学生总分,实现”关联“
    students
      .map(stu => {
        val id: String = stu.id
        val sumScore: Int = sumScoreMap.getOrElse(id, 0)
        id + "," + stu.name + "," + stu.age + "," + sumScore
      }).foreach(println)
  }

  @Test
  //练习2:
  //1.统计年级排名前十学生各科的分数 [学号,姓名,班级,科目,分数]
  def question1(): Unit = {
    //计算学生总分,找到排名前十的学生
    val top10Ids: List[String] = scores
      .groupBy(sco => sco.id)
      .map(kv => {
        val id: String = kv._1
        val sumScore: Int = kv._2.map(_.score).sum
        (id, sumScore) //如果返回的是二元组,则map处理完后会得到一个Map
      })
      .toList //Map中没有排序方法,所以需要转成List
      .sortBy(kv => -kv._2) //降序排序
      .take(10)
      .map(_._1)
    /*
        //将学生和学科数据变成Map的形式
        val stuMap: Map[String, String] = students
          .map(stu => (stu.id, stu.name + "," + stu.clazz)).toMap

        val subMap: Map[String, String] = subjects
          .map(sub => (sub.subId, sub.subName)).toMap

        scores
          //从scores中根据top10Ids过滤出排名前十的学生成绩
          .filter(sco => top10Ids.contains(sco.id))
          .map(sco => {
            val id: String = sco.id
            val subId: String = sco.subId
            val nameClazz: String = stuMap.getOrElse(id, "anonymous,")
            val subName = subMap.getOrElse(subId, "")
            s"$id,$nameClazz,$subName,${sco.score}"
          }).foreach(println)
     */
    //优化
    filterWithIdsAndPrint(top10Ids)
  }

  @Test
  //2.统计总分大于年级平均分的学生 [学号,姓名,班级,总分]
  def question2(): Unit = {
    //计算年级平均分:372.704
    val avgScore: Double = scores
      .map(_.score)
      .sum / students.size.toDouble
    println(avgScore)

    //将学生数据变成Map的形式
    val stuMap: Map[String, String] = students
      .map(stu => (stu.id, stu.name + "," + stu.clazz)).toMap

    scores
      .groupBy(sco => sco.id)
      .map {
        case (id: String, scoList: List[Sco]) =>
          (id, scoList.map(_.score).sum)
      }
      .filter(kv => kv._2 > avgScore)
      .map {
        case (id: String, sumScore: Int) =>
          val nameClazz: String = stuMap.getOrElse(id, "")
          s"$id,$nameClazz,$sumScore"
      }.foreach(println)
  }

  @Test
  //3.统计每科都及格的学生 [学号,姓名,班级,科目,分数]
  def question3(): Unit = {
    //以科目id和科目满分构建一个Map
    val subScoreMap: Map[String, Int] = subjects
      .map(sub => (sub.subId, sub.subScore)).toMap

    //6门科目都及格的学生id构成的List
    val everySubPassStuIds: List[String] = scores
      //将每个学生不及格的科目成绩过滤掉
      .filter(sco => sco.score >= subScoreMap.getOrElse(sco.subId, 0) * 0.6)
      //统计每个学生及格的科目数量
      .groupBy(sco => sco.id)
      .map(kv => (kv._1, kv._2.size))
      .filter(kv => kv._2 == 6)
      .keys
      .toList

    filterWithIdsAndPrint(everySubPassStuIds)
  }

  @Test
  //4.统计每个班级的前三名 [学号,姓名,班级,分数]
  def question4(): Unit = {
    //统计每个学生的总分,以学生id作为key,学生总分作为value构建Map
    val stuScoreMap: Map[String, Int] = scores
      .groupBy(sco => sco.id)
      .map(kv => {
        val id: String = kv._1
        val sumScore: Int = kv._2.map(_.score).sum
        (id, sumScore) //如果返回的是二元组,则map处理完后会得到一个Map
      })

    students
      .map(stu => {
        val sumScore: Int = stuScoreMap.getOrElse(stu.id, 0)
        (stu.id, stu.name, stu.clazz, sumScore)
      })
      //按照班级分组
      .groupBy(t4 => t4._3)
      .flatMap(kv => {
        val stuS: List[(String, String, String, Int)] = kv._2
        //按照总分进行降序排列取每个班级的前三名
        stuS
          .sortBy(t4 => -t4._4)
          .take(3)
          .map(t4 => s"${t4._1},${t4._2},${t4._3},${t4._4}")
      }).foreach(println)
  }

  @Test
  //5.统计偏科最严重的前100名学生 [学号,姓名,班级,科目,分数]
  def question5(): Unit = {
    //归一化处理:每门科目的总分并不是完全相同,都换算成百分制进行计算

    //以科目id和科目满分构建一个Map
    val subScoreMap: Map[String, Int] = subjects
      .map(sub => (sub.subId, sub.subScore)).toMap

    val top100ids: List[String] = scores
      //遍历scores,将所有分数转换为百分制
      .map(sco => {
        val subScore: Int = subScoreMap.getOrElse(sco.subId, 100)
        (sco.id, sco.score / subScore.toDouble * 100)
      })
      //按每个学生分组,计算方差
      .groupBy(t2 => t2._1)
      .map(kv => {
        val id: String = kv._1
        val scoList: List[(String, Double)] = kv._2
        //计算平均分
        val avgScore: Double = scoList.map(_._2).sum / scoList.size
        //计算方差
        val variance: Double = scoList
          .map {
            case (id: String, score: Double) =>
              Math.pow(score - avgScore, 2)
          }.sum / scoList.size
        (id, variance)
      })
      .toList
      .sortBy(t2 => -t2._2)
      .take(100)
      .map(_._1)

    filterWithIdsAndPrint(top100ids)
  }


}

case class Stu(id: String, name: String, age: Int, gender: String, clazz: String)

case class Sco(id: String, subId: String, score: Int)

case class Sub(subId: String, subName: String, subScore: Int)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没钳蟹蟹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值