《快学Scala》第一版第三章练习

发布于:2022-12-07 ⋅ 阅读:(425) ⋅ 点赞:(0)

系列文章目录

《快学Scala》第一版第一章练习

《快学Scala》第一版第二章练习

《快学Scala》第一版第三章练习


前言

这学期开了《Spark编程基础》,需要用到Scala语言,书上写的比较简单,本着学一门语言就应该尽量往深处学的想法,到图书馆借了一本《快学Scala》,英文名《Scala for the Impatient》,争取每周看完两章,并将相应练习写成博客。


练习

1.编写一段代码,将a设置为一个n个随机整数的数组,要求随机数介于0(包含)和n(不包含)之间。

首先引入scala.io.StdIn.readInt包

import scala.io.StdIn.readInt

object Test {
    def main(args: Array[String]): Unit = {
      val n: Int= readInt()       //输入n的值
      val a = new Array[Int](n)     //建立元素个数为n的数组
      for(i <- 0 until a.length){
        a(i) = scala.util.Random.nextInt(n)    //将随机数存入数组,随机数的范围为[0,n)
      }
      print(a.mkString(" "))   //将数组a中每个元素用空格隔开,转换成字符串进行输出
    }
}

2.编写一个循环,将整数数组中相邻的元素置换。例如,Array(1, 2, 3, 4, 5)经过置换后变为Array(2, 1, 4, 3, 5)。

object Test {
    def main(args: Array[String]): Unit = {
      val a = Array[Int](1,2,3,4,5,6,7,8,9,10)     //建立数组a
      println(a.mkString("|"))       //将数组a中每个元素用"|"隔开,转换成字符串进行输出,输出后换行

      //相邻元素进行置换
      for(i <- 0 until a.length by 2 if i < a.length-1 ){   //守护if i < a.length-1 是防止数组a(i + 1)发生越界
        val temp = a(i)
        a(i) = a(i + 1)
        a(i + 1) = temp
      }

      print(a.mkString("|"))   //将数组a中每个元素用"|"隔开,转换成字符串进行输出
    }
}

3.重复前一个练习,不过这一次生成一个新的值交换过的数组。用for/yield。

object Test {
    def main(args: Array[String]): Unit = {
      val a = Array[Int](1,2,3,4,5,6,7,8,9,10,11)     //建立数组a
      println(a.mkString("|"))       //将数组a中每个元素用"|"隔开,转换成字符串进行输出,输出后换行

      //相邻元素进行置换
      //总体思路:设n个元素,前n-1个元素按照下标i为奇数还是偶数,i为偶数便添加为b(i + 1);i为奇数便添加为b(i - 1)
      //        随后单独对最后一号元素进行判断,若下标为偶数,则a中含有奇数个元素,其没有相邻元素进行置换,直接添加为b(n-1)
      //        若下标为奇数,则a中含有偶数个元素,其相邻元素为前一号元素,将其前一号元素添加为b(n-1)
      val b = for(i <- 0 until a.length) yield {
        if(i < a.length - 1){
          if(i % 2 == 0)
            a(i + 1)
          else
            a(i - 1)
        }
        else{
          if(i % 2 == 0)
            a(i)
          else
            a(i - 1)
        }
      }

      print(b.mkString("|"))   //将数组b中每个元素用"|"隔开,转换成字符串进行输出
    }
}

a中有偶数个元素

a中有奇数个元素

4.给定一个整数数组,产出一个新的数组,包含原数组中的所有正值,以原有顺序排列,之后的元素是所有零或负值,以原有顺序排列。

import scala.collection.mutable.ArrayBuffer

object Test {
    def main(args: Array[String]): Unit = {
      val a = Array[Int](3,1,-1,4,2,5,0,-4,0,1,3,-2,0)     //建立数组a
      println("a = " + a.mkString(" "))       //将数组a中每个元素用" "隔开,转换成字符串进行输出,输出后换行

      //总体思路:遍历一次数组,将正数按顺序添加到一个ArrayBuffer中;
      //       再次遍历数组,将0和负数按顺序添加到ArrayBuffer中,再将ArrayBuffer转为Array
      val b = ArrayBuffer[Int]()
      for(i <- 0 until a.length if a(i) > 0)
        b += a(i)
      for(i <- 0 until a.length if a(i) <= 0)
        b += a(i)
      val c = b.toArray
      print("b = " + c.mkString(" "))   //将数组c中每个元素用" "隔开,转换成字符串进行输出
    }
}

5.如何计算Array[Double]的平均值?

object Test {
    def main(args: Array[String]): Unit = {
      val a = Array[Double](3,1,-1,4,2,5,0,-4,0,1,3,-2,0)     //建立数组a
      println("a = " + a.mkString(" "))       //将数组a中每个元素用" "隔开,转换成字符串进行输出,输出后换行
      println("a.avg = " + a.sum / a.length)   //a中数值总数除以a中元素个数
    }
}

6.如何重新组织Array[Int]的元素将它们以反序排列?对于ArrayBuffer[Int]你又会怎么做呢?

Array[Int]借助中间变量进行置换

object Test {
    def main(args: Array[String]): Unit = {
      val a = Array[Int](3,1,-1,4,2,5,0,-4,0,1,3,-2,0,1)     //建立数组a
      println("a = " + a.mkString(" "))       //将数组a中每个元素用" "隔开,转换成字符串进行输出,输出后换行

      for(i <- 0 until a.length / 2){
        val temp = a(i)
        a(i) = a(a.length-1-i)
        a(a.length-1-i) = temp
      }

      println("a = " + a.mkString(" "))       //将数组a中每个元素用" "隔开,转换成字符串进行输出,输出后换行
    }
}

ArrayBuffer[Int]可以直接调用reverse函数进行转置

import scala.collection.mutable.ArrayBuffer

object Test {
    def main(args: Array[String]): Unit = {
      var a = ArrayBuffer[Int](3,1,-1,4,2,5,0,-4,0,1,3,-2,0,1)     //建立数组缓冲a
      println("a = " + a.mkString(" "))       //将数组缓冲a中每个元素用" "隔开,转换成字符串进行输出,输出后换行

      a = a.reverse

      println("a = " + a.mkString(" "))       //将数组缓冲a中每个元素用" "隔开,转换成字符串进行输出,输出后换行
    }
}

在使用时发现,Array也有reverse函数可以调用

7.编写一段代码,产出数组中的所有值,去掉重复项。(提示:查看Scaladoc)

查看Scaladoc后找到相关方法distinct

object Test {
    def main(args: Array[String]): Unit = {
      val a = Array[Int](3,1,-1,4,2,5,0,-4,0,1,3,-2,0,1)     //建立数组a
      println("a = " + a.mkString(" "))       //将数组a中每个元素用" "隔开,转换成字符串进行输出,输出后换行
      println("a = " + a.distinct.mkString(" "))       //将数组a中每个元素用" "隔开,转换成字符串进行输出,输出后换行
    }
}

8.重新编写3.4节结尾的示例。收集负值元素的下标,反序,去掉最后一个下标,然后对每一个下标调用a.remove(i)。比较这样做的效率和3.4节中另外两种方法的效率。

3.4示例为

        val a = Array(2, 3, 5, 7, 11)

        var first = true

        val indexes = for (i <- 0 until a.length if first || a(i) >= 0) yield {

                if (a(i) < 0) first = false;

                i

        }

        for(j <- 0 until indexes.length)

                a(j) = a (indexes(j))

        a.trimEnd(a.length - indexes.length)

重新编写后为:

import scala.collection.mutable.ArrayBuffer

object Test {
    def main(args: Array[String]): Unit = {
      val a = ArrayBuffer[Int](2, -3, 5, 7, -11, -1, 0, 1,-2)
      println("a:" + a.mkString(" "))    //将初始的数组缓冲a输出
      
      //调用currentTimeMillis()设置时间戳,两时间戳相减约等于noName运行时间
      val tm1 = System.currentTimeMillis()
      noName(a)
      val tm2 = System.currentTimeMillis()
      
      println("用时:" + (tm2-tm1))        //将用时输出
      println("a:" + a.mkString(" "))    //输出只剩第一个负数的数组缓冲a
    }

  def noName(a: ArrayBuffer[Int]): Unit = {
    //将各负数下标记录
    var indexes = for(i <- 0 until a.length if a(i) < 0) yield i
    
    //将下标反序,并去除最后一个下标
    indexes = indexes.reverse.dropRight(1)

    //对每一个下标调用a.remove()方法
    for(i <- 0 until indexes.length)
      a.remove(indexes(i))
  }
}

 再求出另外两种方法的时间效率

import scala.collection.mutable.ArrayBuffer

object Test {
    def main(args: Array[String]): Unit = {
      val a = ArrayBuffer[Int](2, -3, 5, 7, -11, -1, 0, 1,-2)
      println("a:" + a.mkString(" "))

      //调用currentTimeMillis()设置时间戳,两时间戳相减约等于noName运行时间
      val tm1 = System.currentTimeMillis()
      noName(a)
      val tm2 = System.currentTimeMillis()

      println("用时:" + (tm2-tm1))
      println("a:" + a.mkString(" "))
    }

  def noName(a: ArrayBuffer[Int]): Unit = {
    var first = true
    var n = a.length
    var i = 0
    while( i < n) {
      if (a(i) >= 0) i += 1
      else{
        if(first) {
          first = false;
          i += 1
        }
        else{
          a.remove(i);
          n -= 1
        }
      }
    }
  }
}

import scala.collection.mutable.ArrayBuffer

object Test {
    def main(args: Array[String]): Unit = {
      val a = ArrayBuffer[Int](2, -3, 5, 7, -11, -1, 0, 1,-2)
      println("a:" + a.mkString(" "))

      //调用currentTimeMillis()设置时间戳,两时间戳相减约等于noName运行时间
      val tm1 = System.currentTimeMillis()
      noName(a)
      val tm2 = System.currentTimeMillis()

      println("用时:" + (tm2-tm1))
      println("a:" + a.mkString(" "))
    }

  def noName(a: ArrayBuffer[Int]): Unit = {
    var first = true
    val indexes = for (i <- 0 until a.length if first || a(i) >= 0) yield {
      if(a(i) < 0) first = false; 
      i
    }
    for(j <- 0 until indexes.length)
      a(j) = a(indexes(j))
    a.trimEnd(a.length - indexes.length)
  }
}

9.创建一个由java.util.TimeZone.getAvailableIDs返回的时区集合,判断条件是它们在美洲。去掉"America/"前缀并排序。

涉及到比对"America/“ 需要使用Array类中的startswith()方法

object Test {
    def main(args: Array[String]): Unit = {
      val times = java.util.TimeZone.getAvailableIDs()
      //去除含有"America/"的数组元素
      var select = for(member <- times if member.startsWith("America/") != true) yield member
      select = select.sorted    //将去除"America/"后的数组进行排序
      println(times.mkString)
      println(select.mkString)
    }
}

10.引入java.awt.datatransfer._并构建一个类型为SystemFlavorMap类型的对象:

val flavors = SystemFlavorMap.getDefaultFlavorMap().asInstanceOf[SystemFlavorMap]

然后以DataFlavor.imageFlavor为参数调用getNativesForFlavor方法,以Scala缓冲保存返回值。(为什么用这样一个晦涩难懂的类?因为在Java标准类库中很难找得到使用java.util.List的代码。)

import java.awt.datatransfer._

object Test {
    def main(args: Array[String]): Unit = {
      //构建对象
      val flavors = SystemFlavorMap.getDefaultFlavorMap().asInstanceOf[SystemFlavorMap]

      //调用getNativesForFlavor()方法,将返回结果转为Array,再转为Buffer
      val buffer = flavors.getNativesForFlavor(DataFlavor.imageFlavor).toArray.toBuffer
      println(buffer)
    }
}

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到