Scala for the Impatient Chapter 4 练习
第1题
设置一个映射,其中包含你想要的一些装备,以及他们的价格。然后构建另一个映射,采用同一组键,但在价格上打9折。
代码如下:
1 | val items = Map("MacBook" -> 9888, "MacBook Pro" -> 20888, "Iphone XS Max" -> 10888) |
测试结果如下:
1 | scala> val items = Map("MacBook" -> 9888, "MacBook Pro" -> 20888, "Iphone XS Max" -> 10888) |
第2题
编写一段程序,从文件中读取单词。用一个可变映射来清点每一个单词出现的频率。读取这些单词的操作可以使用 java.util.Scanner:
1 | val in = new java.util.Scanner(new java.io.File("myfile.txt")) |
或者翻到第9章看看更 Scala的做法。
最后打印出所有单词和他们出现的次数
首先在scala命令行启动目录下新建文本文件file.txt,内容如下:
1 | hello |
采用题干中提到的方法的代码如下:
1 | import scala.collection.mutable.HashMap |
测试结果如下:
1 | scala> val in = new java.util.Scanner(new java.io.File("file.txt")) |
按照第九章的文件处理来做的代码如下:
1 | import scala.io.Source |
测试结果如下:
1 | scala> import scala.io.Source |
第3题
重复前一个练习,这次用不可变的映射。
代码如下:
1 | import scala.collection.immutable.Map |
测试结果如下:
1 | scala> import scala.collection.immutable.Map |
需要注意以下几点:
- Map 是抽象类,无法用 new 关键字来进行实例化
- 在定义 maps 变量时需要使用 var 关键字声明为可变变量
- 在对 key 进行计数时需要采用
+=操作符,且需要用->指向key 所对应的原来的 value
第4题
重复前一个练习,这次用已排序的映射,以便单词可以按顺序打印出来。
代码如下:
1 | import scala.collection.immutable.SortedMap |
测试结果如下:
1 | scala> import scala.collection.immutable.SortedMap |
需要注意的是,SortedMap的基本性质和 Map相同。
第5题
重复前一个练习,这次用 java.util.TreeMap并使之适用于 Scala API。
代码如下:
1 | import scala.collection.JavaConversions.mapAsScalaMap |
测试结果如下:
1 | scala> val in = new java.util.Scanner(new java.io.File("file.txt")) |
第6题
定义一个链式哈希映射,将"Monday"映射到java.util.Calendar.MONDAY,依次类推加入其它日期。展示元素是以插入顺序被访问的。
代码如下:
1 | import scala.collection.mutable.LinkedHashMap |
测试结果如下:
1 | scala> import scala.collection.mutable.LinkedHashMap |
第7题
打印出所有Java系统属性的表格,类似这样:
| 属性名称 | 属性值 |
|---|---|
| java.rutime.name | Java™ SE Runtime Environment |
| sun.boot.library.path | /home/apps/jdk1.6.0_21/jre/lib/i386 |
| java.vm.version | 17.0-b16 |
| java.vm.vendor | sun Microsystems Inc. |
| java.vendor.url | http://java.sun.com/ |
| path.separator | : |
| java.vm.name | Java HotSpot™ Server VM |
| 你需要找到最长键的长度才能正确地打印出这张表格。 |
代码如下:
1 | import scala.collection.JavaConversions.propertiesAsScalaMap |
部分测试结果如下:
1 | scala> import scala.collection.JavaConversions.propertiesAsScalaMap |
第8题
编写一个函数 minmax(values: Array[Int]),返回数组中最小值和最大值的对偶。
- 版本一,采用HashMap,代码如下:
1 | def minmax(values: Array[Int]): HashMap[Int, Int] = { |
测试结果如下:
1 | scala> def minmax(values: Array[Int]): HashMap[Int, Int] = { |
- 版本二,采用Map,代码如下:
1 | def minmax(values: Array[Int]): Map[Int, Int] = { |
测试结果如下:
1 | scala> def minmax(values: Array[Int]): Map[Int, Int] = { |
第9题
编写一个函数 lteqgt(values: Array[Int], v: Int),返回数组中小于v、 等于 v和大于 v 的数量,要求三个值一起返回。
代码如下:
1 | def lteqgt(values: Array[Int], v: Int): Tuple3[Int, Int, Int] = { |
测试结果如下:
1 | scala> def lteqgt(values: Array[Int], v: Int): Tuple3[Int, Int, Int] = { |
需要注意的是,这里用到了 GenTraversableOnce当中的一个聚合函数 count:
1 | abstract def count(p: (A) ⇒ Boolean): Int |
第10题
当你将两个字符串拉链在一起,比如“Hello”.zip("World"),会是什么结果,想出一个讲得通的用例。
测试结果如下:
1 | scala> "Hello".zip("World") |
查看 ScalaDoc,在GenIterableLike当中 zip的文档如下:
1 | abstract def zip[B](that: GenIterable[B]): GenIterable[(A, B)] |
zip会对所有可遍历的集合进行拉链操作,而字符串本身是可遍历的,且是以字符为单位进行遍历,因此出现了上述运行结果。根据文档,返回集合的长度是以 A、B两者较小的长度为准,具体可以再看下下面这个例子:
1 | scala> val string = "Hello".zip("Worldscala") |
这里"Worldscala"后面的"scala"被忽略了。