atlarge对《快学Scala》的笔记(4)

atlarge
atlarge (心有挂碍)

在读 快学Scala

快学Scala
  • 书名: 快学Scala
  • 作者: [美] C. S. 霍斯曼
  • 页数: 408
  • 出版社: 电子工业出版社
  • 出版年: 2012-10
  • 第162页
      // 习题1
      def values(fun: (Int) => Int, low: Int, high: Int) = {
        (low to high).map(v => (v, fun(v)))
      }
    
      // 习题2
      def getMaxValue[T <% Ordered[T]](arr: Array[T]) = {
        arr.reduceLeft((e1, e2) => if(e1 > e2) e1 else e2)
      }
    
      // 习题3
      def factorial(n: Int) = {
        (1 to n).reduceLeft(_ * _)
      }
    
      // 习题4
      def factorial2(n: Int) = {
        (1 to n).foldLeft(1)(_ * _)
      }
    
      // 习题5
      def largest(fun: (Int) => Int, inputs: Seq[Int]) = {
        inputs.map(fun).max
      }
    
      // 习题6
      def largest2(fun: (Int) => Int, inputs: Seq[Int]) = {
        inputs.map(fun).zip(inputs).max._2
      }
    
      // 习题7
      def adjustToPair(fun: (Int, Int) => Int) = {
        (v: (Int, Int)) => fun(v._1, v._2)
      }
    
      // 习题8
      def isCorresponding(strs: Array[String], lengths: Array[Int]) = {
        strs.corresponds(lengths)(_.length == _)
      }
    
      // 习题9
      def myCorresponds[A, B](array: Array[A], that: Seq[B], p: (A, B) => Boolean) = {
        if (array.length != that.length)
          false
        else {
          array.zip(that).foldLeft(true){ (t, v) => t && p(v._1, v._2) }
        }
      }
    
      // 习题9
      // 问题:不用curring,就无法利用类型推断,那么传入的匿名函数是无法用'_'简化的,
      //      只能写成完整版,如下:
      def isCorresponding2(strs: Array[String], lengths: Array[Int]) = {
        myCorresponds(strs, lengths, (str: String, len: Int) => str.length == len)
      }
    
      // 习题10
      // 第一个参数要是换名调用参数,保证调用时condition不被求值,直接传下去,在if中求值
      // 需要用curring,使得不必这样unless(condition, {...})使用unless
      def unless(condition: => Boolean)(block: => Unit) {
        if (!condition) {
          block
        }
      }
    
    
    2013-12-26 12:04:43 回应
  • 第190页
      // 习题1
      def indexes(str: String) = {
        str.zipWithIndex.groupBy(_._1).map { tuple =>
          tuple._1 -> tuple._2.map(_._2).toSet
        }
      }
    
      // 要求mutable map和mutable set以及排序集
      import scala.collection.mutable
      def indexesMutable(str: String) = {
        var res = mutable.HashMap[Char, mutable.LinkedHashSet[Int]]()
        for ((c, i) <- str.zipWithIndex) {
          val set = res.getOrElseUpdate(c, mutable.LinkedHashSet())
          set += i
        }
    
        res
      }
    
      // 习题2
      def indexes2(str: String) = {
        str.zipWithIndex.groupBy(_._1).map { tuple =>
          tuple._1 -> tuple._2.map(_._2).toList
        }
      }
    
      // 习题3
      def filterZero(l: List[Int]) = l.filter(_ != 0)
    
      // 习题4
      def getMapValue(a: Array[String], m: Map[String, Int]) = a.map(m.get(_)).flatMap(x => x)
    
      // 习题5
      def mkString[T](s: Seq[T], sep: String =",") = s.map(_.toString).reduceLeft(_.toString + sep + _.toString)
    
      // 习题6
      // (lst :\ List[Int]())(_::_) 得到和lst一样的整数List
      // (List[Int]() /: lst)(_:+_) 得到和lst一样的整数List
      // 要反序排列,可以
      // (lst :\ List[Int]())((elem, coll) => coll :+ elem) 或者
      // (List[Int]() /: lst)((coll, elem) => elem +: coll)
    
      // 习题7
      val prices = List(5.0, 20.0, 9.95)
      val quantities = List(10, 2, 1)
      prices.zip(quantities).map(Function.tupled(_*_))
    
      // 习题8
      def mkTwoDimArray(a: Array[Double], cols: Int) = a.grouped(cols).toArray
    
      // 并发相关部分没看
      // 习题9
      // 习题10
    
    
    2013-12-29 14:04:20 回应
  • 第208页
      // 习题2
      def swap(v: (Int, Int)) = {
        v match {
          case (x, y) => (y, x)
        }
      }
    
      // 习题3
      import scala.reflect.ClassTag
      def swapInArray[T: ClassTag](a: Array[T]) = a match {
        case Array(x, y, rest @ _*) => Array(y, x) ++ rest
        case _ => a
      }
    
      // 习题4
      abstract class Item
      case class Article(description: String, price: Double) extends Item
      case class Bundle(description: String, discount: Double, items: Item*) extends Item
      case class Multiple(count: Int, item: Item) extends Item
    
      def price(item: Item): Double = item match {
        case Article(_, p) => p
        case Bundle(_, discount, items @ _*) => items.map(price).sum - discount
        case Multiple(count, item) => count * price(item)
      }
    
      // 习题5
      def leafSum(lst: List[Any]): Int = lst match {
        case (x: Int) :: tail => x + leafSum(tail)
        case (x: List[Any]) :: tail => leafSum(x) + leafSum(tail)
        case _ => 0
      }
    
      // 习题6
      sealed abstract class BinaryTree
      case class Leaf(value: Int) extends BinaryTree
      case class Node(left: BinaryTree, right: BinaryTree) extends BinaryTree
    
      def leafSum(tree: BinaryTree): Int = tree match {
        case Leaf(v) => v
        case Node(l, r) => leafSum(l) + leafSum(r)
      }
    
      // 习题7
      sealed abstract class Tree
      case class TreeLeaf(value: Int) extends Tree
      case class TreeNode(children: Tree*) extends Tree
    
      def leafSum(tree: Tree): Int = tree match {
        case TreeLeaf(v) => v
        case TreeNode(children @ _*) => children.map(leafSum).sum
      }
    
      // 习题8
      sealed abstract class Tree2
      case class Leaf2(value: Int) extends Tree2
      case class Node2(op: Char, children: Tree2*) extends Tree2
    
      def eval(tree: Tree2): Int = tree match {
        case Leaf2(v) => v
        case Node2(op, children @ _*) => op match {
          case '+' => children.map(eval).sum
          case '-' => -children.map(eval).sum
          case '*' => children.map(eval).product
        }
      }
    
      // 习题9
      def sumList(lst: List[Option[Int]]) = lst.map(_.getOrElse(0)).sum
    
      // 习题10
      type FunType = Double => Option[Double]
      def compose(fun2: FunType, fun1: FunType) = (arg: Double) => fun1(arg) match {
        case None => None
        case Some(result) => fun2(result)
      }
    
    2013-12-30 15:58:38 回应
  • 第256页
    // 习题1
    class ImmutablePair[T, S](fst: T, snd: S){
      private val pair = (fst, snd)
      def swap() = new ImmutablePair(pair._2, pair._1)
      override def toString() = "(" + pair._1 +", " + pair._2 + ")"
    }
    
    object ImmutablePair {
      def apply[T, S](fst: T, snd: S) = new ImmutablePair(fst, snd)
    
      //习题3
      def swap[T, S](p: ImmutablePair[T, S]) = ImmutablePair(p.pair._2, p.pair._1)
    }
    
    // 习题2
    class MutablePair[T](fst: T, snd: T) {
      private var pair = (fst, snd)
      def swap() {pair = (pair._2, pair._1)}
      override def toString() = "(" + pair._1 + ", " + pair._2 + ")"
    }
    
    object MutablePair {
      def apply[T](fst: T, snd: T) = new MutablePair(fst, snd)
    }
    
      // 习题4
      // 因为Student是Person的子类型,子类型可以自动转为超类型。
    
      // 习题5
      // RichInt是为了服务Int,同时存在Int到RichInt的隐式转换。
      // 使用视图界定时Int隐式转换为RichInt,从而可以转换为Comparable[Int]。
    
      // 习题6
      def middle[T](a: Iterable[T]) = a.slice((a.size-1) / 2, a.size).head
    
      // 习题7
      // 略
    
      // 习题8
      // 因为可变类型改变的是自身的第一个元素,该元素类型为T,替换进来的元素类型为R,R >: T;
      // 将超类型当作子类型是行不通的。
    
      // 习题9
      // 假定可以不用限制方法参数,那么对实际类型为NastyDoublePair的Pair[Any]调用replace("Hello")时,
      // 调用的是NastyDoublePair中重写了的replaceFirst,而其要求的是Double,所以会出错:type mismatch。
    
    // 习题10
    class Pair[S, T](private var first: S, private var second: T) {
    
      def swap(implicit ev1: T =:= S, ev2: S =:= T) = {
        val temp = first
        first = second
        second = temp
      }
    
      override def toString() = "(" + first + ", " + second + ")"
    }
    
    
    2014-01-02 13:55:10 1人喜欢 1回应