Scala学习整理[第二十四-二十六章 抽取器和XML]<Programming In Scala>

第二十四章 抽取器

package SecondWithProgrammingInScala

/**
  * 抽取器
  *
  * 抽取器可以在匹配的同时进行分解 ,可以直接抽出里面的值
  * 相当与 is是非语句 + get方法
  * 通常配合模式匹配使用 ,在之前章节中匹配并获取数组值 Array(x,y)=> x+y ,也是抽取器
  *
  * 之前的模式匹配和样本类 ,标注了case的样本类可以将参数列表作为匹配项
  * 实质就一个语法糖 ,为样本类同时声称了一个伴生对象(同名object) ,并提供了了apply和unapply
  * 然后模式匹配时候调用unapply ,用于匹配和拆解参数
  *
  * 使用样本类 ,匹配表达式和构造器一致 ,数据和模型是一一对应的
  * 使用抽取器 ,可以为一个模型添加不同的抽取方式(对Email字串执行多种方式的抽取) ,数据和模型是分开的
  */

object Email {
  //抽取方法 : 匹配并分解值
  def unapply(s: String): Option[(String, String)] = {
    val parts = s split "@"
    if (parts.length == 2) Some(parts(0), parts(1)) else None
  }

  //注入方法 : 相对的
  def apply(user: String, domain: String) = user + "@" + domain
}

//比较是否是连续的email
object TwiceEmail {
  def unapply(s: String): Option[String] = {
    val length = s.length / 2
    val half = s.substring(0, length)
    if (half == s.substring(length)) Some(half) else None
  }
}

//判断是否全为大写
object UpperCase {
  //没有设置apply方法 ,在模式匹配时 UpperCase() 是没有参数的
  //如果想要利用(输出)匹配到的参数 ,可以使用 str @ UpperCase()
  def unapply(s: String): Boolean = s.toUpperCase == s
}

//拆解域名
object Domain {
  //拆解成seq
  def unapplySeq(whole: String): Option[Seq[String]] = Some(whole.split("""\."""))
}

object ExtractorsApp {
  //配合模式匹配使用 ,当匹配的是抽取器 ,会自动调用unapply方法获取返回值
  def parser(s: String) = {
    s match {
      case Email(user, domain) => println(user + " AT " + domain)
      case _ => print("not an email address")
    }
  }

  def userTwiceUpper(s: String): Unit = {
    s match {
      case Email(TwiceEmail(user@UpperCase()), domain) => println("Twice,Upper :  " + user + " AT " + domain)
      case Email(user@UpperCase(), domain) => println("Upper :  " + user + " AT " + domain)
      case Email(TwiceEmail(user), domain) => println("Twice :  " + user + " AT " + domain)

      case Email(user@UpperCase(), domain@UpperCase()) => println("Upper :  " + user + " AT " + "Upper :  " + domain)
      case _ => println("not match :  " + s)
    }
  }

  def isSinaEmail(s: String): Boolean = s match {
    case Email(user, Domain("sina", _*)) => true
    case _ => false
  }

  def main(args: Array[String]): Unit = {
    val emails = List("liaoad@asiainfo.com", "liaoadliaoad@aisainfo.com", "LIAOLIAO@sina.com", "LIAOAD@QQ.COM")

    emails.foreach(userTwiceUpper)
    emails.foreach(x => if (isSinaEmail(x)) println(x))
  }
}

/**
  * 正则表达式
  */
object RegexApp {
  def main(args: Array[String]): Unit = {
    import scala.util.matching.Regex
    //使用 """ 三引号表示一个原始字符串 ,里面的字符串默认不为\转义 (\d即匹配数字 ,\.即匹配.)
    //RichString提供了 .r 方法 ,将字符串转化成Regex
    val Decimal =
    """(-)?(\d+)(\.\d*)?""".r
    val input = "for -0.1 to 99 by 3"

    //在字符串中查询数字 生成Seq 打印
    for (s <- Decimal findAllIn input) println(s)
  }
}

第二十五章 注解

注解和Java的用法基本相同

第二十六章 使用XML

package SecondWithProgrammingInScala

/**
  * 使用XML
  *
  * 读写/查询/拆解
  * scala可以方便的操作xml ,并在里面嵌入代码 ,或是代码中描述xml
  */

import scala.xml.{Elem, Node, XML}

abstract class CCTherm {
  val description: String
  val yearMade: Int
  val dateObtained: Elem
  val bookPrice: Int
  val purchasePrice: Int
  val condition: Int

  override def toString: String = description

  //序列化
  def toXml =
  <cctherm>
    <description>
      {description}
    </description>
    <yearMade>
      {yearMade}
    </yearMade>
    <dateObtained>
      {dateObtained}
    </dateObtained>
    <bookPrice>
      {bookPrice}
    </bookPrice>
    <purchasePrice>
      {purchasePrice}
    </purchasePrice>
    <condition>
      {condition}
    </condition>
  </cctherm>

  //反序列化(通过搜索节点)
  def fromXML(node: Node): CCTherm =
  new CCTherm {
    override val condition: Int = {
      node \ "condition"
    }.text.trim.toInt
    override val description: String = {
      node \ "description"
    }.text
    override val bookPrice: Int = {
      node \ "bookPrice"
    }.text.trim.toInt
    override val purchasePrice: Int = {
      node \ "purchasePrice"
    }.text.trim.toInt
    override val yearMade: Int = {
      node \ "yearMade"
    }.text.trim.toInt
    override val dateObtained: Elem = XML.loadString({
      node \ "dateObtained"
    }.toString.trim)
  }
}

object XMLApp {

  //保存到文件
  def saveAsFile(fileName: String, node: Node) = {
    XML.save(fileName + ".xml", node, "UTF-8", true, null)
  }

  //从文件读取
  def getXMLFromFile(fileName: String): Elem = {
    XML.loadFile(fileName + ".xml")
  }

  //只匹配一层
  def proc(node: Node): String =
  node match {
    case <dateObtained>
      {dateObtained}
      </dateObtained> =>
      "it's obtained in " + {
        dateObtained \\ "year"
      }.toString.trim
    case _ => "unknow"
  }

  def main(args: Array[String]): Unit = {
    //匿名子类
    val term = new CCTherm {
      override val condition: Int = 9
      override val description: String = "hot dog #5"
      override val bookPrice: Int = 2199
      override val purchasePrice: Int = 500
      override val yearMade: Int = 1952
      override val dateObtained: Elem =
        <base>
          <year>2006</year>
          <month>3</month>
          <day>12</day>
          03.12.2006
        </base>
    }

    //获取xml
    val termXML = term.toXml
    println(termXML)

    //保存xml
    saveAsFile("XMLUtilTest", termXML)
    val xmlFromFile = getXMLFromFile("XMLUtilTest")

    //转换成对象
    val obj = term.fromXML(xmlFromFile)
    println(obj)

    //将xml转化成text文字
    val termText = termXML.text
    println(termText)

    //通过签名找到xml子元素(只在根节点下查找)
    val description = termXML \ "description"
    println(description)
    println(termXML \ "day")

    //深度搜索查找子元素
    val dayOfDateObtained = termXML \\ "day"
    println(dayOfDateObtained)

    //模式匹配查找
    println(proc(termXML))
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值