【问题标题】:Pattern matching on a tuple元组上的模式匹配
【发布时间】:2018-11-09 14:52:23
【问题描述】:

对于以下条件 - 已为 Tuple2(BigDecimal,BigDecimal) 定义了模式匹配

  (r.get(0), r.get(1)) match {
    case (r0: BigDecimal, r1: BigDecimal) => (bigDecimalNullToZero(r0), bigDecimalNullToZero(r1))
    case (r0,r1)  => {
      error(s"Unable to compare [$r0] and [$r1]"); (0L,0L)
    }
  }

为什么无法识别匹配项?

【问题讨论】:

  • @TzachZohar r0 和 r1 的类型在第二张截图中显示为BigDecimal
  • 我可以看到,我在问r 的类型——或者更准确地说,r.get 的签名
  • @DanW 不知道为什么会有用:在那个时刻,预期的(/正确的?)第一个匹配已经被绕过
  • @TzachZohar 哦,我明白你的意思了。是的,类型是 Any 。那么compile 时间类型不是runtime 类型.. 我想这是有道理的.. 没有等待不.. 运行时类型检查实际上是模式匹配的关键部分:那么为什么类型r.get(): Any 导致这个?
  • object TestTupleMatch extends App { val bd1 = BigDecimal(51302213.000000) val bd2 = BigDecimal(51302213.000000) (bd1, bd2) match { case (r0: BigDecimal, r1: BigDecimal) => println("matched") case (r0,r1) => println("Unable to compare [$r0] and [$r1]") } } 上面的程序给出了匹配的结果。这意味着它可以正常工作。我使用 scala 2.12.4 和 java 1.8.0_144

标签: scala pattern-matching tuples


【解决方案1】:

我将假设在这种情况下 r 的类型为 org.apache.spark.sql.Row - 如果是这种情况,您只是在使用 wrong BigDecimal 类 - 您正在匹配Scala 内置 scala.math.BigDecimal,而 Spark 在后台使用 java.math.BigDecimal

所以 - 如果您使用 Java 的类进行匹配,这应该可以按预期工作:

(r.get(0), r.get(1)) match {
  case (r0: java.math.BigDecimal, r1: java.math.BigDecimal) => (bigDecimalNullToZero(r0), bigDecimalNullToZero(r1))
  case (r0,r1)  => {
    error(s"Unable to compare [$r0] and [$r1]"); (0L,0L)
  }
}

我用这个完整的例子来测试这个:

import spark.implicits._

val df = Seq(
  (BigDecimal(2.1), BigDecimal(2.3)) // using Scala's BigDecimal to build DF
).toDF("name", "hit_songs")

df.foreach { r: Row => (r.get(0), r.get(1)) match {
  case (s1: BigDecimal, s2: BigDecimal) => println("found Scala BigDecimals")
  case (s1: java.math.BigDecimal, s2: java.math.BigDecimal) => println("found Java BigDecimals")
  case (s1, s2) => println(s"Not found")
}}

// prints: found Java BigDecimals

P.S.您通常可以使用 Row 的 unapply 函数从 Row 中简化此类“提取”,即匹配 Row(a, b, ...)

df.map {
  case Row(s1: java.math.BigDecimal, s2: java.math.BigDecimal, _*) => (s1, s2)
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-12
    • 2014-08-27
    • 2015-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多