scala,spark初体验

一、实验环境

Ubuntu 20.04 - VMware Workstation

java - openjdk version “1.8.0_312”

Scala code runner version 2.11.12

二、List常规用法

  1.  实验内容
  1. 定义一个列表List1,内容为(“a”, “b” ,“c”, “d”, “e”, “f”, “g”) ,在列表List1开头添加指定列表List2(“m”, “n”, “a”, “b” , “e”)的元素;
  2. 在(1)的基础上,去除List1列表的重复元素, 然后从指定位置 0 开始查找元素d第一次出现的位置,并输出结果;
  3. 对上述List1进行列表反转;
  4. 对上述List1按降序排序。

2.代码实现

object Task1{

  def main(args:Array[String]) : Unit = {

    println("(1)")

    //定义一个列表List1,内容为(“a”, “b” ,“c”, “d”, “e”, “f”, “g”)

    var List1: List[String] = List("a", "b", "c", "d", "e", "f", "g")

    println("Initialize List1: "+List1)

    //定义列表List2,内容为(“m”, “n”, “a”, “b” , “e”)

    val List2: List[String] = List("m", "n", "a", "b", "e")

    println("Initialize List2: "+List2)

    //使用concat方法在列表List1开头添加列表List2的元素

    List1=List.concat(List2,List1)

    println("Add List2 at the beginning of List1: "+List1)

   

    println("(2)")

    //使用distinct方法去除List1列表的重复元素

    List1=List1.distinct

    println("Remove duplicate elements in List1: "+List1)

    //使用indexOf方法从指定位置 0 开始查找元素d第一次出现的位置,并输出结果

    println("find the first occurrence of \"d\", starting at location 0: "+List1.indexOf("d",0))

   

    println("(3)")

    //使用reverse方法对List1进行列表反转

    List1=List1.reverse

    println("reverse List1: "+List1)

   

    println("(4)")

    //使用sorted方法对List1排序,再使用reverse方法得到list1降序排序

    List1=List1.sorted.reverse

    println("sort List1 down: "+List1)

  }

}

3.测试结果

 

三、scala面向对象编程

  1.  实验内容

定义一个抽象类Shape,包含两个函数用以计算面积area()以及周长perimeter(),以此继承出计算长方形Rectangle、圆形Circle、梯形Trapezium的类。其中Rectangle类有2个成员变量:width与height;Circle类有一个成员变量radius;Trapezium有3个成员变量top,bottom,height。定义两个特质并在各个派生类中使用:MyMath定义加减乘除函数操作,PrintInfo用于输出shape的相关信息,例如:该长方形的周长为xx,面积为xx。

要求:实现4个类,2个特质,以及完成主函数内容(给定相关参数,分别计算3种形状的周长与面积)

2.代码实现

//定义MyMath特质,并定义加减乘除函数操作

//拥有MyMath特质的类可以使用MyMath中定义的加减乘除函数进行计算操作

trait MyMath{

  def add(a:Double, b:Double):Double={

    var res:Double = 0.0

    res = a + b

    return res

  }

  def sub(a:Double, b:Double):Double={

    var res:Double = 0.0

    res = a - b

    return res

  }

  def mul(a:Double, b:Double):Double={

    var res:Double = 0.0

    res = a * b

    return res

  }

  def div(a:Double, b:Double):Double={

    var res:Double = 0.0

    res = a / b

    return res

  }

}



//定义PrintInfo特质,用于输出shape的相关信息

trait PrintInfo{

  def printinfo(){

    println(this.toString)

  }

}



//定义抽象类Shape,包含两个函数用以计算面积area()以及周长perimeter()

abstract class Shape(){

  def area(): Double

  def perimeter(): Double

}



//Rectangle类继承Shape抽象类,并拥有上述定义的两个特质

class Rectangle(w:Double, h:Double) extends Shape() with MyMath with PrintInfo{

  //Rectangle类有2个成员变量:width与height

  var width:Double =w

  var height:Double =h

  //重载area面积计算函数

  override def area(): Double = {

    var res:Double = 0.0

    //调用MyMath中的加减乘除函数进行长方形面积的计算

    res = mul(width,height)

    return res

  }

  //重载perimeter周长计算函数

  override def perimeter(): Double ={

    var res:Double = 0.0

    //调用MyMath中的加减乘除函数进行长方形周长的计算

    res = mul(2.0,add(width,height))

    return res

  }

  def printInfo(){

    var toString="该长方形的周长为"+perimeter+",面积为"+area

    println(toString)

  }

}



//Circle类继承Shape抽象类,并拥有上述定义的两个特质

class Circle(r:Double) extends Shape() with MyMath with PrintInfo{

  //Rectangle类有1个成员变量:radius

  var radius:Double =r

  //重载area面积计算函数

  override def area(): Double = {

    var res:Double = 0.0

    //调用MyMath中的加减乘除函数进行圆形面积的计算

    res = mul(3.14, mul(radius, radius))

    return res

  }

  //重载perimeter周长计算函数

  override def perimeter(): Double ={

    var res:Double = 0.0

    //调用MyMath中的加减乘除函数进行圆形周长的计算

    res = mul(3.14, mul(2.0, radius))

    return res

  }

  def printInfo(){

    var toString="该圆形的周长为"+perimeter+",面积为"+area

    println(toString)

  }

}



//Trapezium类继承Shape抽象类,并拥有上述定义的两个特质

class Trapezium(t:Double, b:Double, h:Double) extends Shape() with MyMath with PrintInfo{

  var top:Double =t

  var bottom:Double =b

  var height:Double =h

  //重载area面积计算函数

  override def area(): Double = {

    var res:Double = 0.0

    //调用MyMath中的加减乘除函数进行梯形面积的计算

    res = div(mul(add(top ,bottom),height),2.0)

    return res

  }

  //重载perimeter周长计算函数

  override def perimeter(): Double ={

    var res:Double = 0.0

    //调用MyMath中的加减乘除函数进行梯形周长的计算

    res = add(add(top,bottom),mul(2.0,math.sqrt(add(mul(height,height),mul(div(sub(bottom,top),2.0),div(sub(bottom,top),2.0))))))

    return res

  }

  def printInfo(){

    var toString="该梯形的周长为"+perimeter+",面积为"+area

    println(toString)

  }

}



object  Task2{

  def main(args: Array[String]) {

    val r=new Rectangle(10,30)

r.printInfo;



    val c=new Circle(10)

    c.printInfo;

   

    val t=new Trapezium(10,30,10)

    t.printInfo;

  }

}

3.测试结果

 

四、统计学生成绩

  1.  实验内容

要求:尽量用函数式编程

学生的成绩清单格式如下所示,第一行为表头,各字段意思分别为学号、性别、课程名1,课程名2等,后面每一行代表一个学生的信息,各字段之间用空白符隔开,数据与习题2.3相同。

给定任何一个如下格式的清单(不同清单里课程数量可能不一样),要求尽可能采用函数式编程,统计出以下数据:

  1. 各门课程的平均成绩,方差,及格率,以及80分以上的人数;
  2. 每个同学所有课程的平均成绩;
  3. 每门课程排名前5位,以及后5位的学生学号。

 

2.代码实现

import scala.io.Source

object Ex03 {

    def main(array: Array[String])={

          // 假设数据文件在当前目录下传入

          val inputFile = Source.fromFile("data.txt")

          //”\\s+“是字符串正则表达式,将每行按空白字符(包括空格/制表符)分开

          // 由于可能涉及多次遍历,同 toList 将 Iterator 装为 List

          // originalData 的类型为 List[Array[String]]

          val originalData = inputFile.getLines.map(_.split("\\s+")).toList

          //使用head方法获取第一行再使用drop方法获取第一行中的课程名

          val courseName = originalData.head.drop(2)

          // 去除第一行剩下的数据为学生信息数据

          val students = originalData.tail



          // 统计函数1,参数为需要常用统计的行

          //用到了外部变量 courseNum,属于闭包函数

          //作用是统计出各门课程的平均成绩,方差,及格率,以及80分以上的人数

          def statistic1 (lines:List[Array[String]])={

            // for 推导式,对每门课程生成一个四元组,分别表示平均成绩,方差,及格率,以及80分以上的人数

            for (i<-2 to courseName.length+1)yield{

              // 取出需要统计的列,将其中元素转化为Double

              val temp = lines map{

                elem=>elem(i).toDouble

              }

              // 新列表中的元素为temp中元素与平均值差的平方

              val temp2 = temp map{

                elem=>(elem-temp.sum/lines.length)*(elem-temp.sum/lines.length)

              }

              //平均值:使用sum方法对统计列求和,再除以列表长度lines.length

              //方差:使用sum方法对temp2求和,再除以列表长度lines.length

              //及格率:filter方法过滤出成绩>=60的元素,用length方法求出过滤后列表长度再除以原列表长度

              //80分以上的人数:filter方法过滤出成绩>=80的元素,用length方法求出过滤后列表长度

              (temp.sum/lines.length,temp2.sum/lines.length,temp.filter(s=>s>=60.0).length.toDouble/lines.length,temp.filter(s=>s>=80.0).length)

            }

          }

         

          //统计函数2,统计每个同学所有课程的平均成绩

          def statistic2 (lines:List[Array[String]])={

            // for 推导式,对每个同学生成一个二元组,分别是学生的学号和平均成绩

            for (i<-0 to lines.length-1)yield{

              //学号:对每一行使用toList方法转成List后,用head方法得到第一个元素就是学生的学号

              //平均成绩:对每一行使用drop(2)方法保留成绩信息,用toArray方法转成Array后将每个元素转成Double再求和

                  //而后除以课程数量

              (students(i).toList.head,students(i).drop(2).toArray.map(s=>s.toDouble).sum/courseName.length.toDouble)

            }

          }

         

          // 输出结果函数1,用于输出统计函数1的结果

          def printResult1(theresult:Seq[(Double,Double,Double,Int)]): Unit ={

            // 遍历前调用 zip 方法将课程名容器和结果容器合并,合并结果为二元组容器

            (courseName zip theresult)foreach{

              case (name,result)=>

                println(f"${name+":"}%-10s${result._1}%5.2f${result._2}%12.2f${result._3}%9.2f${result._4}%8.0f")

            }

          }



          //输出结果函数3,用于统计并输出每门课程排名前5位,以及后5位的学生学号。

          def printResult3(): Unit ={

            var num=2  //课程起始列

            (courseName)foreach{

              case (name)=>

                println(f"\n${name+"_max(5):"}%-10s")

                //输出每门课程排名前5位的学生学号

                //将成绩信息转成Array后,使用sortBy方法根据课程所在列排序

                //而后反转为降序排序,使用take方法取前5位同学的学号输出

                students.toArray.sortBy(s=>s(num)).reverse.take(5).foreach(s=>print(s(0)+"\t"))

                println(f"\n${name+"_min(5):"}%-10s")

                //输出每门课程排名后5位的学生学号,方法同上

                //区别是在使用sortBy方法根据课程所在列排序后不需要反转

                students.toArray.sortBy(s=>s(num)).take(5).foreach(s=>print(s(0)+"\t"))

                num = num+1

            }

            println()

          }



          println("(1)")

          val  allResult1 = statistic1(students)

          println("course  average    variance     pass     >80")

          printResult1(allResult1)

          println("(2)")

          val  allResult2 = statistic2(students)

          println("    Id  average")

          for (i<-0 to allResult2.length-1){

              println(f"${allResult2(i)._1}%-10s${allResult2(i)._2}%5.2f")

            }

          print("(3)")

          printResult3()

    }

}

3.测试结果

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值