快学Scala习题解答第十三章---------集合

1.编写一个函数,给定字符串,产生出一个包含所有字符的下标的映射。举例来说,index("Mississippi")应返回一个映射,让'M'对应集{0},'i'对应集{1,4,7,10},依此类推。使用字符到可变集映射。另外,你如何保证集是经过排序的?

运行结果:

Map(M -> TreeSet(0), s -> TreeSet(2, 3, 5, 6), p -> TreeSet(8, 9), i -> TreeSet(1, 4, 7, 10))



2.重复前一个练习,这次使用字符到列表不可变映射

 

运行结果:

Map(s -> List(6, 5, 3, 2), M -> List(0), i -> List(10, 7, 4, 1), p -> List(9, 8))


3.编写一个函数,从一个整型链表里去除所有零值。

运行结果:

List(1, 2, 3, 6, 7, 10)



4.编写一个函数,接受一个字符串的集合,以及一个从字符串到整数值的映射。返回整型的集合,其值为能和集合中某个字符串相对应的映射的值。举例来说,给定Array("Tom","Fred","Harry")和Map("Tom"->3,"Dick"->4,"Harry"->5),返回Array(3,5)。提示:用flatMap将get返回的Option值组合在一起。

运行结果:

3 5


5.实现一个函数,与mkString相同,使用reduceLeft.

运行结果:

3|1|2



6.给定整型列表lst,(lst:\List[Int]())(_::_)得到什么? (List[Int]/:lst)(_:+_)又得到什么?如何修改它们中的一个,以对原列表进行反向排列。

运行结果:

List(1, 2, 3, 4, 5)
List(1, 2, 3, 4, 5)
List(5, 4, 3, 2, 1)


7.在13.11节中,表达式(prices zip quantities) map { p => p._1 * p._2 }有些不够优雅。我们不能用(prices zip quantities) map {  _ * _},因为_*_是一个带两个参数的函数,而我们需要的是一个带单个类型为元组的参数的函数,Function对象的tupled方法可以将带两个参数的函数改为以元组为参数的函数。将tupled用于乘法,以便我们用它来映射由对偶组成的列表。

运行结果:

List(50.0, 40.0, 9.95)
List(50.0, 40.0, 9.95)
List(50.0, 40.0, 9.95)


8.编写一个函数,将Double数组转换成二维数组。传入列数作为参数。举例来说,Array(1,2,3,4,5,6)和三列,返回Array(Array(1,2,3),Array(4,5,6))。用grouped方法。

运行结果:

1.0 2.0 3.0
4.0 5.0 6.0


9.Harry Hacker写了一个从命令行接受一系列文件名的程序。对每个文件名,他都启动一个新的线程来读取文件内容并更新一个字母出现的频率映射,声明为:

val frequencies = new scala.collection.mutable.HashMap[Char,Int] with scala.collection.mutable.SynchronizedMap[Char,Int]

当读到字母c时,他调用

frequencies(c) = frequencies(c).getOrElse(c,0) + 1

为什么这样得不到正确答案?如果他用下面的方式实现呢:

import scala.collection.JavaConversions.asScalaConcurrentMap

val frequencies:scala.collection.mutable.ConcurrentMap[Char,Int] = new java.util.concurrent.ConcurrentHashMap[Char,Int]


并发问题,并发地修改和遍历集合并不安全,很可能会引发代码中的错误。修改后的代码只是比简单地使用同步方式执行所有方法更加高效,并不能解决并发的问题。


10.Harry Hacker把文件读取到字符串中,然后想对字符串的不同部分用并行集合来并发地更新字母出现频率映射。他用了如下代码:

val frequencies = new scala.collection.mutable.HashMap[Char,Int]

for ( c < str.par) frequencies(c) = frequencies(c).getOrElse(c,0) + 1

为什么说这个想法很糟糕?要真正地实现并行计算,他应该怎么做呢?(提示:用aggregate)

因为并行中访问和修改共享变量结果不可预知。

解释一下这段代码:

aggregate是一个柯里化函数,第一个参数是我们要存放最终结果的变量S。然后两个参数是两个函数F1,F2。

aggregate会将集合分成不同的分区,在每个分区上并行地调用第一个函数F1并将结果保存在每个分区自己的变量S上。

F1的两个参数分别是结果S(a)和每个分区集合中的字符(b)。这样经过F1函数,每个分区的S变量中就按(k,v)的形式统计出了自己分区字母的频率。

熟悉hadoop的同学明白这一步就像是Map的过程。然后调用第二个函数F2进行reduce.

将每个分区的结果S进行合并,这里用到了foldLeft,将合并的结果保存到一个新的HashMap里。result代表新的结果,map1,map2分别为两个分区经过第一步后的结果S。


运行结果:

Map(s -> 3, f -> 4, a -> 3, d -> 3)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

self-motivation

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值