Scala 中的数据结构&模式匹配练习

Scala 中的数据结构&模式匹配练习

数据结构

  • 编写一段代码,将 a 设置为一个 n 个随机整数的数组,要求随机数介于 0和 n 之间。
  def main(args: Array[String]): Unit = {
    randomArray(10).foreach(println)
  }

  def randomArray(n:Int):Array[Int]={
    val rand = new scala.util.Random()
    val array = new Array[Int](n)
    for(i <- array) yield rand.nextInt(n)
  }
1
2
7
4
4
9
7
2
9
9
  • 编写一个循环,将整数数组中相邻的元素置换。 比如 Array(1, 2, 3, 4,5)置换后为 Array(2, 1, 4, 3, 5)
    var array = Array(1,2,3,4,5)
    //跳跃遍历
    for(i <- 0 until (array.length,2)){
      if(i < array.length -1){
        var temp = array(i)
        array(i) = array(i + 1)
        array(i + 1) = temp
        //println(array(i))
      }
    }
    array.foreach(println)
2
1
4
3
5
  • 给定一个整数数组,产出一个新的数组,包含原数组中的所有正值,以原有顺序排列,之后的元素是所有零或负值,以原有顺序排列。
def specialSort(array: Array[Int]):Array[Int]={
    var newArray = new Array[Int](array.length)
    var index:Int = 0
    for(i <- 0 to newArray.length-1){
      if(array(i) > 0) {

        newArray(index) = array(i)
        index = index + 1
      }

    }
    for(i <- 0 to newArray.length-1){
      if(array(i) <= 0) {

        newArray(index) = array(i)
        index = index + 1
      }
    }
    newArray
  }
  • 创建一个由 java.util.TimeZone.getAvailableIDs 返回的时区集合, 并只显示以 America/前缀开头的时区,并且有序。
def getTimeZoneofUS(): ArrayBuffer[String] ={
    val allTimeZone = java.util.TimeZone.getAvailableIDs
    val timeZoneofUs = ArrayBuffer[String]()  //可变数组
    for(i <- 0 to allTimeZone.length - 1){
      if(allTimeZone(i).startsWith("America/")) {
        timeZoneofUs.append(allTimeZone(i))
      }
    }
    timeZoneofUs
  }
  • 设置一个映射,其中包含你想要的一些装备,以及它们的价格。然后根据这个映射构建另一个新映射,采用同一组键,但是价格上打 9 折。
def changePrice(map:scala.collection.mutable.Map[String,Int]):scala.collection.mutable.Map[String,Int]={
    for((k,v) <- map) yield (k, v * 0.9)
    map
  }
  • 编写一段 WordCount 函数,统计传入的字符串中单词的个数
def wordCount(s:String): mutable.HashMap[String,Int] ={
    val count = new mutable.HashMap[String,Int]()
    for(word <- s.split("\\s+")){
      //传入的参数是(key,default)这种形式,
      // 返回值是:如果有key那就get(key),
      // 如果没有,就返回default,
      count(word) = count.getOrElse(word,0) + 1
    }
    count
  }
  • 重复上一个练习,使统计后的单词有序
def wordCoun2t(s:String): mutable.HashMap[String,Int] ={
    val count = new mutable.HashMap[String,Int]()
    for(word <- s.split("\\s+")){
      //传入的参数是(key,default)这种形式,
      // 返回值是:如果有key那就get(key),
      // 如果没有,就返回default,
      count += (word -> (count.getOrElse(word,0) + 1))
    }
    count
  • 重复前一个练习,使用 java.util.TreeMap 进行实现,并使之适用于 Scala API
  def wordCount3(s:String): scala.collection.mutable.Map[String,Int] ={
    var count:scala.collection.mutable.Map[String,Int] = new java.util.TreeMap[String,Int]
    for(word <- s.split("\\s+")){
      //传入的参数是(key,default)这种形式,
      // 返回值是:如果有key那就get(key),
      // 如果没有,就返回default,
      count += (word -> (count.getOrElse(word,0) + 1))
    }
    count
  }
  • 在 REPL 中打印出所有 Java 系统属性的表格,需要有格式,如下:
    在这里插入图片描述
scala> import scala.collection.JavaConversions._
import scala.collection.JavaConversions._
scala> val props:scala.collection.Map[String,String] =
System.getProperties()
props: scala.collection.Map[String,String] =
Map(env.emacs -> "", java.runtime.name -> Java(TM) SE Runtime
Environment, sun.boot.library.path ->
/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents
/Home/jre/lib, java.vm.version -> 25.131-b11,
user.country.format -> CN, gopherProxySet -> false,
java.vm.vendor -> Oracle Corporation, java.vendor.url ->
http://java.oracle.com/, path.separator -> :, java.vm.name ->
Java HotSpot(TM) 64-Bit Server VM, file.encoding.pkg -> sun.io,
user.country -> US, sun.java.launcher -> SUN_STANDARD,
sun.os.patch.level -> unknown, java.vm.specification.name ->
Java Virtual Machine Specification, user.dir ->
/Users/wuyufei, java.runtime.version -> 1.8.0_131-b11,
java.awt.graphicsenv -> sun.awt.CGraphicsEnvironment,
java.endorsed.dirs -> /Library/Java/Jav...
scala> val keyLengths = for( key <- props.keySet ) yield
key.length
keyLengths: scala.collection.Set[Int] = Set(10, 25, 14, 20, 29,
28, 21, 9, 13, 17, 12, 7, 18, 16, 11, 26, 23, 8, 19, 15)
scala> val maxKeyLength = keyLengths.max
maxKeyLength: Int = 29
scala> for(key <- props.keySet){
| print(key)
| print(" " * (maxKeyLength - key.length))
| print(" | ")
| println(props(key))
| }
  • 编写一个函数 minmax(values:Array[Int]), 返回数组中最小值和最大值的对偶
def minmax(values:Array[Int]):(Int,Int) ={
    (values.min,values.max)
  }
  • 编写一个函数 indexes,给定字符串,产出一个包含所有字符下标的映射。举例来说: indexes(“Mississippi”)应返回一个映射,让’M’对应集{0},‘i’对应集{1, 4,7, 10},依次类推。使用字符到可变集的映射,注意下标的集应该是有序的。
def indexes(str:String):mutable.HashMap[Char,SortedSet[Int]]={
     var map = new mutable.HashMap[Char,SortedSet[Int]]()
     var i = 0
     str.foreach{
       c =>
       map.get(c) match {
         case Some(result) => map(c) = result + i
         case None => map += (c-> SortedSet{i})
       }
       i += 1
     }
     map
  }
  • 编写一个函数,从一个整型链表中去除所有的零值
def removeZero(list:java.util.ArrayList[Int])={
    val newList = new java.util.ArrayList[Int]
    val it:util.Iterator[Int] = list.iterator()
    while(it.hasNext){
      if(it.next() != 0)  newList.add(it.next())
    }

    newList
  }
  • 编写一个函数,接受一个字符串的集合,以及一个从字符串到整数值的映射。返回整形的集合,其值为能和集合中某个字符串相对应的映射的值。举例来说,给定 Array(“Tom”,”Fred”,”Harry”)Map(“Tom”->3,”Dick”->4,”Harry”->5),返回Array(3,5)。提示:用 flatMap 将 get 返回的 Option 值组合在一起
def m_map2(array:Array[String],map: Map[String , Int])={
    array.flatMap(map.get(_))
  }
  • 实现一个函数,作用与 mkStirng 相同,提示:使用 reduceLeft 实现试试
def newMkString(list:List[String],str:String)={
    println(list.reduceLeft(opreate))
    def opreate(c1:String,c2:String):String={
      c1 + str + c2
    }
  }
  • 给定整型列表 lst(lst :\ List[Int]())(_ :: _)得到什么? (List[Int]() /: lst)(_ :+ _)又得到什么?如何修改他们中的一个,以对原列表进行反向排列?
var list = List(1,2,3,4,5,3,4,3,4,2,4,2,4,2)

    println((list:\List[Int]())(_::_))
    println((List[Int]() /: list)(_ :+ _))

    //对原列表进行反向排列
    println((List[Int]() /: list)((a,b)=> b :: a))
List(1, 2, 3, 4, 5, 3, 4, 3, 4, 2, 4, 2, 4, 2)
List(1, 2, 3, 4, 5, 3, 4, 3, 4, 2, 4, 2, 4, 2)
List(2, 4, 2, 4, 2, 4, 3, 4, 3, 5, 4, 3, 2, 1)
  • 编写一个函数,将 Double 数组转换成二维数组。传入列数作为参数。距离来说,
    传入 Array(1,2,3,4,5,6)和 3 列,返回 Array(Array(1,2,3), Array(4,5,6))
def changeArray(array:Array[Int],num:Int):Array[Array[Int]]={
    var newArray = new Array[Array[Int]](array.length / num)
    var number = 0
    for(i <-  0 to array.length / num - 1){
      newArray(i) = new Array[Int](num)
      for(j <- 0 to num - 1){
        newArray(i)(j) = array(number)
        number = number + 1
      }
    }
    newArray
  }

模式匹配

  • 利用模式匹配,编写一个 swap 函数,接受一个整数的对偶,返回对偶的两个组成部件互换位置的新对偶
def swap[S,T](tuple:(S,T)):(T,S)={
    tuple match{
      case (a,b) => (b,a)
    }
  }
  • 利用模式匹配,编写一个 swap 函数,交换数组中的前两个元素的位置,前提条件是数组长度至少为 2
def swap(array: Array[Any])={
    array match{
      case Array(a,b,rest @_*) => Array(b,a)++rest
      case _ => array
    }
  }
  • 编写计算 Item 价格的通用函数。
abstract class Item
case class Article(description: String, price: Double) extends Item
case class Bundle(description: String, discount: Double, items: Item*) extends Item
val special = Bundle("Father's day special", 20.0,
Article("Scala for the Impatient", 39.95),
Bundle("Anchor Distillery Sampler", 10.0,
Article("Old Potrero Straight Rye Whiskey", 79.95),
Article("Junípero Gin", 32.95)))
def getPrice(it:Item):Double={
    it match {
      case Article(_,p) => p
      case Bundle(_,disc,its @ _*) => its.map(getPrice _).sum - disc
    }
  }
  • 通过 case 类制作一颗二叉树。
sealed abstract class BinaryTree
case class Leaf(value : Int) extends BinaryTree
case class Node(left : BinaryTree,right : BinaryTree) extends BinaryTree

编写一个通用函数计算所有叶子节点中的元素之和。

def sumofLeaves(tree:BinaryTree):Int={
    tree match {
      case Node(a,b) => sumofLeaves(a) + sumofLeaves(b)
      case Leaf(v) => v
    }
  }




val  r = Node(Leaf(3),Node(Leaf(3),Leaf(9)))
    println(sumofLeaves(r))
  • 扩展前一个练习中的树,使得每个节点可以有任意多的后代,并重新实现计算函数。 完成下面这棵树的叶子节点元素统计:
Node(Node(Leaf(3),Leaf(8)),Leaf(2),Node(Leaf(5)))
def sumofLeaves(tree:Multitree):Int={
    tree match {
      case Node(t @_*) => t.map(sumofLeaves).sum
      case Leaf(v) => v
    }
  }
  • 扩展前一个练习中的树,使得每个非叶子节点除了后代之外,能够存放一个操作符。然后编写一个 eval 函数来计算它的值。举例来说:
    在这里插入图片描述
    上面这棵树的值为(3 * 8) + 2 + (-5) = 21
    新的 case 类如下:
sealed abstract class BinaryTree
case class Leaf(value: Int) extends BinaryTree
case class Node(op: Char, leafs: BinaryTree*) extends BinaryTree

完成下面的树的计算:

Node('+', Node('*', Leaf(3), Leaf(8)), Leaf(2), Node('-', Leaf(5)))
def eval(tree:BinaryTree):Int= {
tree match {
case Node(op, leafs@_*) => op match {
case '+' => leafs.map(eval _).sum
case '-' => -leafs.map(eval _).sum
case '*' => leafs.map(eval _).product
}
case Leaf(x) => x
}
}
  • 编写一个函数,计算 List[Option[Int]]中所有非 None 值之和。不得使用 match 语句。
def sum(lst: List[Option[Int]]) = lst.map(_.getOrElse(0)).sum

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值