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)