scala練習問題(14)-モードマッチングとサンプルクラス

12014 ワード

14.1 JDK発行パッケージにはsrcがあります.zipファイルにはJDKのほとんどのソースコードが含まれています.サンプルラベルを解凍して検索します(正規表現case[^:]+:).検索して//で始まり[Ff]allsを含みますか?thrのコメントは、//Falls throughや//just fall thruのようなコメントをキャプチャします.JDKのプログラマーたちがJava符号化の習慣を守っていると仮定して、注釈を書く場所にこれらの注釈を書いたとしますが、どのくらいの割合のサンプルが次の分岐に落ちるのでしょうか.理解できなかった=.14.2パターンマッチングを利用して、1つのswap関数を編纂して、1つの整数の対偶を受け入れて、対偶の2つの構成部品の交換位置の新しい対偶偏関数の使い方を返して、使用する時パラメータのタイプを制定することができる
 def swap[W,Y](tup:(W,Y))={
    tup match{
      case (a,b) => (b,a);
    }
  }

14.3パターンマッチングを利用して、swap関数を作成し、配列中の最初の2つの要素の位置を交換し、前提条件は配列長が少なくとも2つの配列マッチングであり、残りのすべてのパラメータの表現方式は_*である.変数名の代わりにar@*
 def swap(arr:Array[Int])={
    arr match{
      case Array(a,b,ar@_*) => Array(b,a,ar);
    }
  }

14.4 ItemのサブクラスとしてサンプルクラスMultipleを追加します.例えば、Multiple(10,Article(「Blackwell Toster」)は、10個のトースターを記述する.もちろん、Bundleでも別のMultipleでも、2番目のパラメータの位置で任意のItemを受け入れることができます.price関数を拡張して、新しいサンプルに対応します.
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(it:item):Double = it match{
    case Article(_,p)=>p;
    case Bundle(_,disc,its @ _ *)=>its.map(price).sum -disc;
    case Multiple(count,it) => price(it)*count;
  }

14.5リーフノードにのみ値を格納するツリーをリストで作成できます.たとえば、リスト((3 8)2(5))は、*/|*2*/|3 8 5というツリーを記述しますが、リスト要素の中には数字であり、リストであるものもあります.Scalaでは異機種リストを持つことができないので、List[Any]を使用する必要があります.leafSum関数を作成し、すべてのリーフノードの要素の和を計算し、パターンマッチングで数字とリストを区別します.
 def LeafSum(li:List[Any]):Int={
    var sum=0;
    li.foreach{
      l => l match{
        case list:List[Any] => sum=sum+LeafSum(list);
        case t:Int=>sum=sum+t;
      }
    }
    sum;
  }
  println(LeafSum(List(List(3,8),2,List(5))));

14.6このような木を作るより良い方法はサンプル類を使うことです.二叉木から始めてもいいです.
sealed abstract class BinaryTree case class Leaf(value : Int) extends BinaryTree case class Node(left : BinaryTree,right : BinaryTree) extends BinaryTree
すべてのリーフノードの要素の和を計算する関数を作成します.
サンプルクラスを使用するには、このクラスがこのファイル内にのみ表示されることを示すシールクラスの形式を使用することを推奨します.
 sealed abstract class BinaryTree;
  case class Leaf(value:Int) extends BinaryTree;
  case class Node(left:BinaryTree,right:BinaryTree) extends BinaryTree;
  case class Nodes(btree:BinaryTree*) extends BinaryTree;
  case class sNode(oper:String,node:BinaryTree*) extends BinaryTree;
  def leafsum(btree:BinaryTree):Int={
    var sum=0;
    btree match{
      case Node(a,b) =>sum=sum+leafsum(a)+leafsum(b);
      case Leaf(a) => sum=sum+a;
      case Nodes(btr@_*) => sum=sum+btr.map(leafsum).sum;
    }
    sum
  }

14.7前の練習中のツリーを拡張して、各ノードが任意に多くの子孫を持つことができ、leafSum関数を再実現する.5番目の問題のツリーは、次のコードで表すことができます.
sealed abstract class BinaryTree;
  case class Leaf(value:Int) extends BinaryTree;
  case class Node(left:BinaryTree,right:BinaryTree) extends BinaryTree;
  case class Nodes(btree:BinaryTree*) extends BinaryTree;
  case class sNode(oper:String,node:BinaryTree*) extends BinaryTree;
  def leafsum(btree:BinaryTree):Int={
    var sum=0;
    btree match{
      case Node(a,b) =>sum=sum+leafsum(a)+leafsum(b);
      case Leaf(a) => sum=sum+a;
      case Nodes(btr@_*) => sum=sum+btr.map(leafsum).sum;
    }
    sum
  }

14.8前の練習中のツリーを拡張し、各非リーフノードが子孫を除いてオペレータを保存できるようにします.次にeval関数を作成して値を計算します.たとえば、+/|*2-/|3 8の木の値は(3*8)+2+(-5)=21です.
 sealed abstract class BinaryTree;
  case class Leaf(value:Int) extends BinaryTree;
  case class Node(left:BinaryTree,right:BinaryTree) extends BinaryTree;
  case class Nodes(btree:BinaryTree*) extends BinaryTree;
  case class sNode(oper:String,node:BinaryTree*) extends BinaryTree;
  def leafsum(btree:BinaryTree):Int={
    var sum=0;
    btree match{
      case Node(a,b) =>sum=sum+leafsum(a)+leafsum(b);
      case Leaf(a) => sum=sum+a;
      case Nodes(btr@_*) => sum=sum+btr.map(leafsum).sum;
    }
    sum
  }
  def eval(btree:BinaryTree):Int={

    btree match{
      case sNode(oper,btr@_*) => if(oper=="+") btr.map(eval).sum else if(oper=="*") btr.map(eval).reduceLeft(_*_) else if(oper=="-") btr.map(eval).foldLeft(0)(_-_) else  btr.map(eval).reduceLeft(_/_)
      case Leaf(v)=>v
    }


  }

14.9リスト[Option[Int]]のすべてのNone値の和を計算する関数を記述する.match文は使用できません.
 def evalList(list:List[Option[Int]]):Int={
   list.map(_.getOrElse(0)).sum;
  }

14.10 Double=>Option[Double]という2つのタイプの関数を組み合わせて、同じタイプの別の関数を生成する関数を作成します.いずれかの関数がNoneを返す場合は、組合せ関数もNoneを返します.例:
  def f(x:Double) = if(x>=0) Some(sqrt(x)) else None;
  def g(x:Double) = if(x!=1) Some(1/(x-1)) else None;
  def compose(x:Double=>Option[Double],y:Double=>Option[Double]):(Double=>Option[Double])={
    (f:Double) => if(x(f)==None || y(f)==None) None else if(x(f).get> y(f).get) x(f) else y(f)
  }