数据结构
- 编写一段代码,将 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