关闭

[Scala]Scala学习笔记九 提取器

标签: scala提取器applyunapplyunapplySeq
407人阅读 评论(0) 收藏 举报
分类:

1. apply和update方法

Scala允许你使用如下函数调用语法:

f(arg1, arg2, ...)

扩展到可以应用于函数之外的值.如果f不是函数或方法,那么这个表达式就等同于调用:

f.apply(arg1, arg2, ...)

如果它出现在赋值语句的等号左侧:

f(arg1, arg2, ...) = value

则等同于调用:

f.update(arg1, arg2, ..., value)

应用场景:

(1) 常被用于数组和映射:

val scores = new scala.collection.mutable.HashMap[String, Int]
scores("Bob") = 100 // 调用scores.update("Bob", 100)
val bobScores = scores("Bob") // 调用scores.apply("Bob")

(2) 同样经常用在伴生对象中,用来构造对象而不用显示的使用new:

class Fraction (n: Int, d: Int){
  ...
}

object Fraction{
  def apply(n: Int, d: Int) = new Fraction(n, d)
}

// 使用
val result = Fraction(3, 4) * Fraction(2, 5)

2. 提取器

所谓提取器就是一个带有unapply方法的对象.可以把unapply方法理解为伴生对象中apply方法的反向操作.apply方法接受构造参数,然后将他们变成对象.而unapply方法接受一个对象,然后从中提取值(通常这些值就是当初用来构造该对象的值).

例如上面例子中的Fraction类,apply方法从分子和分母创建出一个分数,而unapply方法则是去取出分子和分母:

(1) 可以在变量定义时使用:

// a b 分别被初始化成运算结果的分子和分母
var Fraction(a, b) = Fraction(3, 4) * Fraction(2, 5)

(2) 也可以用于模式匹配:

// a 和 b 分别绑到分子和分母
case Fraction(a, b) =>  ...

通常而言,模式匹配可能会失败,因此unapply方法返回的是一个Option.它包含一个元组,每个匹配到的变量各有一个值与之对应.下面中返回一个Option[(Int, Int)]

class Fraction (n: Int, d: Int){
  ...
}

object Fraction{
  def apply(n: Int, d: Int) = new Fraction(n, d)
  def unapply(input: Fraction) = if( input.den == 0 ) None else Some( (input.num, input.den) )
}

备注

分母为0时返回None,表示无匹配

在上面例子中,apply和unapply互为反向,但不一定总是互为反向.我们可以用提取器从任何类型的对象中提取信息.例如我们可以从字符串中提取名字和姓氏:

// 提取器
object Name{
    def unapply(input: String) = {
      val pos = input.indexOf(" ")
      if(pos == -1) Node
      else Some( (input.substring(0, pos), input.substring(pos + 1)) )
    }
}

val author = "Lionel Messi"
// 调用Name.unapply(author)
val Name(first, last) = author
// First Name is Lionel and last name is Messi
println("First Name is " + first + " and last name is " + last)

3. 带单个参数或无参数的提取器

在Scala中,并没有只带一个组件的元组.如果unapply方法要提取单值,则应该返回一个目标类型的Option:

object Number {
  def unapply(input: String) : Option[Int] = {
    try{
      Some (Integer.parseInt(input.trim))
    }
    catch{
      case ex: NumberFormatException => None
    }
  }
}

可以使用这个提取器,从字符串中提取数字:

val Number(n) = "1990"

提取器也可以只是测试输入的数据而并不将其值提取出来,只需unapply方法返回Boolean:

object IsContainZero{
  def unapply(input: String) = input.contains("0")
}

4. unapplySeq方法

如果要提取任意长度的值的序列,我们需要使用unapplySeq来命名我们的方法.它返回一个Option[Seq[A]],其中A是被提取的值的类型:

object Names{
  def unapplySeq(input: String): Option[Seq[String]] = {
    if(input.trim == "") None else Some(input.trim.split("\\s+"))
  }
}

val namesStr = "Tom Lily Lucy"
val Names(first, second, third) = namesStr
// the first name is Tom and the second name is Lily and the third name is Lucy
println(s"the first name is $first and the second name is $second and the third name is $third")
0
0
查看评论

使用Scala提取器

Scala语言是函数类型、也是面向对象型的编程语言。 他的语法非常简洁,简洁到连方法的括号,语句结尾的分号等等都可以适当的省略掉。 同时,他也提供了非常强大的API供我们使用。 先展示一下他的提取器在模式匹配中的应用吧。 一、首先定义两个提取器 object Symbol { ...
  • jason5186
  • jason5186
  • 2015-02-12 11:29
  • 2030

Scala入门到精通——第二十五节 提取器(Extractor)

作者:摇摆少年梦 视频地址:http://www.xuetuwuyou.com/course/12本节主要内容 apply与unapply方法 零变量或变量的模式匹配 提取器与序列模式 scala中的占位符使用总结 1. apply与unapply方法apply方法我们已经非常熟悉了,它帮助我们无...
  • lovehuangjiaju
  • lovehuangjiaju
  • 2015-08-15 06:38
  • 11236

第28讲:Scala提取器Extractor

所谓提取器,就是从表达式获取具体值。 其作用,可以根据某一规则,非常方便的获取到想要的值提取器在数组的应用实例代码 def match_arr(arr:Any) = arr match{ case Array(0) => println("array:" +...
  • pzw_0612
  • pzw_0612
  • 2015-08-09 08:44
  • 1759

Scala 提取器与注解深度解析之编程进阶(6)

本篇博客主要分为两部分:一:提取器 二:注解一 :提取器理论: 所谓提取器就是一个带有unapply方法的对象。你可以吧unapply方法当做是半生对象中apply方法的反向操作。 (1)apply方法接受构造参数,然后将他们变成对象。 (2)而unapp...
  • erfucun
  • erfucun
  • 2016-08-13 20:37
  • 1019

【Scala 提取器】Scala 提取器(Extractor)

提取器是从传递给它的对象中提取出构造该对象的参数。 Scala 标准库包含了一些预定义的提取器,我们会大致的了解一下它们。 Scala 提取器是一个带有unapply方法的对象。unapply方法算是apply方法的反向操作: unapply接受一个对象,然后从对象中提取值,提取的值通常是用来构造该...
  • u013421629
  • u013421629
  • 2017-12-27 16:05
  • 153

【Scala】抽取器

引子由于样本类和构造器模式相关联,所以在模式匹配中常使用样本类做数据的解构和分析。 有些情况下,或许希望能够在不创建关联的样本类的前提下编写出类似的模式匹配,此时抽取器(Extractor)可以用来定义与对象表达解耦的模式。抽取email地址的例子问题假设你需要分析一些代表email地址的字符串:...
  • JasonDing1354
  • JasonDing1354
  • 2016-03-10 17:12
  • 1832

Scala学习笔记1 - 基础

本文档针对scala 2.10.x,由于scala目前发展迅速,因此可能会和其他版本的不同。 ===概述          scala是一门以java虚拟机(JVM)为目标运行环境并将面向对象和函数式编程的最佳特性结...
  • guohecang
  • guohecang
  • 2016-08-04 11:47
  • 751

SCALA学习笔记(一)

变量 获取变量的值是一个耗时的工作时,可以考虑使用lazy var. lazy val forLater = someTimeConsumingOperation() scala> val first :: rest = List(1, 2, 3) first: Int = 1...
  • bluishglc
  • bluishglc
  • 2015-02-27 08:46
  • 23541

快学scala 第十一章 操作符 读书笔记及习题答案代码

chapter 11 操作符 标签:快学scala 一、笔记 scala种可以在反引号中包含几乎任何字符序列, val 'val' = 42 所有的操作符都是左结合的,除了以冒号(:)结尾的操作符,和赋值操作符。用于构造列表的::操作符是又结合的。1...
  • refuil
  • refuil
  • 2016-07-22 09:22
  • 1176

Scala 提取器

Scala中的模式可以通过case class独立的定义。在此基础上一个名为unapply的方法被定义用于被称为提取器的东西。下例中分别定义了两个提取器对象(apply,unapply): object Twice { def apply(x: Int): Int = x * ...
  • zzguiji
  • zzguiji
  • 2015-04-28 17:03
  • 156
    个人资料
    • 访问:1517570次
    • 积分:22609
    • 等级:
    • 排名:第378名
    • 原创:624篇
    • 转载:133篇
    • 译文:60篇
    • 评论:189条
    博客专栏
    文章分类
    最新评论