1. 程式人生 > >《快學scala》12章練習答案

《快學scala》12章練習答案

最近看了看《快學scala》,比較好的點在於這本書每一章後面都有一些練習,可以自己去做一下,對於掌握知識來講還是不錯的(像是以前上學後面的習題一樣)。

我不知道哪裡有答案,也沒有認真找過,就自己做了做。

iteye上有一個人寫了前幾章的答案,可以參考一下,連結為:http://ivaneye.iteye.com/blog/1843331,遺憾的是這個人只寫到第九章,我上面的連結也是第九章,後面就沒有了。

為什麼我要寫第12章?

其實前面的練習我都沒有特別認真的做,簡單寫了寫,也參照了一下上面的部落格(非常感謝),12章是將簡單的高階函式,對於scala這樣講函式式與面向物件很好的結合的語言,高階函式是必須掌握的內容,所以我也就花心思做了做練習,並且將10個題的答案寫了下來。

我的答案就正確嗎?

只能說,我根據題目都按照他的思想實現了內容,至於答案是不是最優的,這應該是不可能的。

僅供參照

如果有不同,歡迎指點

題目簡單提一下,可以參照書籍。

練習1:利用函式的函式引數生成對偶集合

這個沒什麼,就是簡單地函式引數的利用而已。


    //第一題  LX12_1

    def values(func:(Int)=>Int,low:Int,high:Int){
            for( i<- low to high){
               println("("+i+","+func(i)+")")
            }
} //呼叫函式 def func(x:Int):Int=x*x values(func,-5,5)
練習2:利用reduceLeft得到陣列中的最大元素

這個只要每次返回一個大的值就可以,我用了 if比較大小 懶。。。。


    //第二題  LX12_2
    def getMaxByReduceLeft(arr:Array[Int]): Int ={
        arr.reduceLeft((a,b)=>{if(a > b) a;else b})
    }
    //呼叫函式
    val arr=Array(1,2,3,4,5,6
,7,2,3,5) println(getMaxByReduceLeft(arr))

練習3:使用to和reduceLeft實現階乘,不得使用迴圈和遞迴

我覺得我這個寫的有點問題,我預設的型別是Long的,但是練習4說要考慮n<1的情況
因此我就無視了
第三和第四題都是有點問題的


    //第三題 LX12_3
    //只考慮 n>1 且 n為Int的情況的解決
    def getFactorialByReduceLeft(num:Long):Long={
        (1:Long).to(num).reduceLeft(_*_)
    }
    //呼叫函式
    println(getFactorialByReduceLeft(10:Long))

練習5:輸出在給定輸入序列中給定函式的最大值,不得使用迴圈和遞迴

這個提示和第二題唯一的不同就是比較的函式的大小而已,不過我用了一個ans一直記錄函式最大值,這樣子最後才能返回需要的也就是函式的最大值


  //第五題   LX12_5
    def LX12_5(func:(Int)=>Int,inputs:Seq[Int]):Int={
            var ans:Int=0
            inputs.reduceLeft((a,b)=>{
               // println(func(a)+"  "+func(b))
                if(func(a) > func(b)){ans=func(a); a}
                else {ans=func(b); b}
            })
        ans
    }
    //測試函式
    def func2(x:Int)=10 *x-x*x
    println(LX12_5(func2,1 to 10))

練習6:對比第5題,返回函式的最大值時的輸入值,不得使用迴圈和遞迴

第五題剛好反過來,需要求最大值時候的輸入值,只要讓ans記錄輸入值就行了


      //第六題 LX12_6
    //一個意思 沒什麼的
    def LX12_6(func:(Int)=>Int,input:Seq[Int]):Int ={
        input.reduceLeft((a,b)=>{
            // println(func(a)+"  "+func(b))
            if(func(a) > func(b))a
            else b
        })
    }
    //測試函式
    def func3(x:Int)=10*x
    println(LX12_6(func3,1 to 3))

練習7:建立一個函式返回一個能接受對偶(tuple2)為引數的函式並能接受一個計算的函式引數

這個題很有意思,首先,通過 zip操作得到的實際上是一個元祖為基礎的vector,而進行map的時候不能簡單地map(_+_),因為他不是兩個int,而是一個tuple2
建立的函式要求能夠在map中去處理,看程式碼。。。


         //第七題 LX12_7
    val pairs=(1 to 10) zip (11 to 20)
   //我們都知道map可以每次去處理一個值,但是他不接受tuple
  //所以ajustToPair剛好解決這個問題,能夠接受tuple2,並返回另一個函式
    def ajustToPair(func:(Int,Int)=>Int)=(pair:Tuple2[Int,Int])=>{func(pair._1,pair._2)}
    //測試函式
    println(pairs.map(i=>ajustToPair(_ + _)(i)))

練習8:利用corresponds和科裡化比較字串序列中每個字元的長度是否和一個整形陣列中的值一一對應

這個看看書上的例子很容易就寫出來了


//第八題LX12_8
    val tmpStr=Array("hello","scala","postbird")
    val tmpLen=Array(5,5,8)
//    val tmpLen=Array(5,5,7)
 println(tmpStr.corresponds(tmpLen)(_.length==_))

練習9:不使用科裡化實現第八題

題目說上一題應該是第七題,也就是使用 zip集合map來實現
當然還是要藉助我們的ajustToPair函式的
最後我用了res來記錄,使用foreach結合 && 操作記錄最後是false和true
我寫的比較麻煩,但是也實現了。不知到有沒有別的方式


//第九題LX12_9
    //不知道前一個聯絡指的是 7 還是8  應該是 7 因為7用了zip
    //然後用了比較麻煩的實現
    val tmpStr_2=Array("hello","scala","postbird")
    val tmpLen_2=Array(5,5,8)
//    val tmpLen_2=Array(5,5,7)
    val pairs_2=tmpStr_2 zip tmpLen_2
    def ajustToPair_2(func:(String,Int)=>Boolean)=(pair:Tuple2[String,Int])=>{func(pair._1,pair._2)}
    var res:Boolean=true
    pairs_2.map(i=>ajustToPair_2(_.length == _)(i)).foreach(b=>res=res&&b)
    println(res)

練習10:參照until根據控制抽象實現一個unless

一定是需要換名排程,另外需要科裡化,不然太麻煩
但實際上 換名排程我只是瞭解個皮毛


//第十題 LX12_10
    //換名呼叫和科裡化是需要的 可以最簡潔的表示
    //省略了() 冒號和 => 的空格是一定要有的
    def unless(condition: =>Boolean)(block: =>Unit){
        if(condition){
            block
            unless(condition)(block)
        }
    }
    //測試函式
    //意思是:除非 到了2,否則就一直輸出
    var tmpNum=10
    unless(tmpNum!=2){
        tmpNum-=1
        println(tmpNum)
    }

程式碼:

我在碼雲存了一個程式碼片段