1. 程式人生 > >Scala練習(十二)

Scala練習(十二)

\1. 編寫函式 values(fun: (Int) => Int, low:Int, high: Int), 該函式輸出一個集合,對應給定區間內給定函式的輸入和輸出。比如,values(x=> x * x, -5, 5)應該產生一個對偶的集合(-5, 25), (-4, 16), (-3, 9), …., (5, 25)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
object valueTest extends App {

  def values(func: (Int) => Int, low: Int, high: Int)
= { val result = (low to high).map( p => { (p, func(p)) } ); result } def func(x: Int) = { x * x } values(func, 1, 5).foreach(item => { println(item._1) println(item._2) }) }

\2. 如何用 reduceLeft 得到陣列中最大元素?

1
2
3
4
5
6
7
8
9
10
11
object
reduceLeftTest extends App {
val testData = (1 to 10).toArray println(testData.reduceLeft((num1, num2) => { if (num1 > num2) { num1 } else { num2 } })) }

\3. 用 to 和 reduceLeft 實現階乘函式,不得使用迴圈和遞迴。

1
2
3
object produceTest extends App {
  println((1 to 10).reduceLeft(_ * _))
}

\4. 前一個實現需要處理一個特殊情況,即 n < 1 的情況。展示如何用foldLeft來避免這個需要。

1
2
3
object produceTest extends App {
  println((1 to -10).foldLeft(1)(_ * _))
}

\5. 編寫函式 largest(fun:(Int) => Int, inputs: Seq[Int]), 輸出在給定輸入序列中給定函式的最大值。舉例來說,largest(x => 10 * x - x * x, 1 to 10) 應該返回 25,不得使用迴圈和遞迴。

1
2
3
4
5
6
7
8
object largestTest extends App {
  def largest(func: (Int) => Int, inputs: Seq[Int]) = {
    val opResult = inputs.map(func(_))
    opResult.max
  }               

  println(largest( x => 10 * x - x * x, 1 to 10))
}

\6. 修改前一個函式,返回最大的輸出對應的輸入。舉例來說,largestAt(fun: (Int) => Int, inputs: Seq[Int])應該返回5. 不得使用迴圈遞迴

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
object largestTest extends App {
  def largest(func: (Int) => Int, inputs: Seq[Int]) = {
    val opResult = inputs.map(item => {(item, func(item))})
    val max = opResult.reduceLeft((item1, item2) => {
      if (item1._2 > item2._2) {
        item1
      } else {
        item2
      }
    })

    max._1
  } 
  
  println(largest( x => 10 * x - x * x, 1 to 10))
}

\7. 要得到一個序列的對偶很容易,比如:

1
    val pairs = (i to 10) zip (11 to 20)

假定你想要對這個序列做某種操作—-比如,給對偶中的值求和。但你不能直接用:

1
    pairs.map(_ + _)

函式 _ + _ 接收兩個 Int 作為引數,而不是(Int, Int)對偶。編寫函式 adjustToPair, 該函式接受一個型別為(Int, Int) => Int, 並返回一個等效的、可以以對偶作為引數的函式。舉例來說就是: adjustToPair(_ * _)((6, 7))應得到42.

然後用這個函式通過map計算出各個對偶的元素之和

1
2
3
4
5
6
7
8
object adjustToPairTest extends App {
  def adjustToPair(fun: (Int, Int) => Int)(item: (Int, Int)) = {
    fun(item._1, item._2)
  }

  val pairs = (1 to 10) zip (11 to 20)
  pairs.map(item => adjustToPair(_ + _)(item)).foreach(println)
}

\8. 在12.8節中,你看到了用於兩組字串陣列的corresponds方法。做出一個方法的呼叫,讓它幫我們判斷字串數組裡的所有元素的長度是否和某個給定整數陣列相對應。

1
2
3
4
5
6
7
8
object correspondsTest extends App {
  val a = Array("aaaaa", "bbbbbb", "ccc")
  val b = Array("aaa", "bbb", "ccc")
  val c = Array(5, 6, 3)

  println(a.corresponds(c)(_.length == _))
  println(b.corresponds(c)(_.length == _))
}

\9. 不使用柯里化實現 corresponds 。 然後嘗試從以前一個練習的程式碼來呼叫。你遇到什麼問題?

1
型別推斷會有問題

\10. 實現一個 unless 控制抽象,工作機制類似 if, 但條件是反過來的。第一個引數需要是換名呼叫的引數嗎?你需要柯里化嗎?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
object unlessTest extends App {
  def unless(condition: => Boolean)(block: => Unit) {
    if (!condition) {
      block
    }
  }

  val n = 10;
  unless(n == 1) {
    println(n)
  }
}

需要換名和柯里化