【问题标题】:Pattern matching on big/long case classes大/长案例类的模式匹配
【发布时间】:2016-08-25 08:04:11
【问题描述】:

有没有一种更易读、更健壮(重构)的方式来匹配这样的案例类?

示例

案例分类

包含许多“字段”的非常长的案例类。

case class Data(name: String, time: Long, ..., userId: Option[UUID] ..., orders: Int, ... ) //more fields fields more

模式匹配:变体 a

有效。但是当字段位置发生变化时容易出错。一个最终计数_

res match {
  case data@Data(_,_,_,_,_,_,Some(id),_,_,_,6,_,_) => (id, data.orders)
  case _ => ... 

} 

模式匹配:变体 b

也可以。对变化的订单很稳定。在警卫中进行更多检查会变得非常麻烦。还必须重复读取值。

res match {
  case data: Data if data.userId.isDefined && data.orders == 6 => (data.userId.get,data.orders)
  case _ => ...
} 

问题改写

有没有一种方法可以结合变体 A 和 B 以获得两种方法的好处?

【问题讨论】:

  • 我知道这不一定有帮助 - 但看起来你真正的问题是有一个如此复杂的案例类开始。如果可能,请考虑将其分解为较小的案例类的层次结构,这些小案例类包含在 Data 案例类中的字段中。这并不是说这不是一个有趣的问题:)

标签: scala pattern-matching


【解决方案1】:

您可以使用自定义提取器:

res match {
  case ExtractUserIdAndOrders(Some(id), 6) => ...
  case _ => ...
}

在哪里

object ExtractUserIdAndOrders {
  def unapply(data: Data) = Some((data.userId, data.orders))
}

如果您只需要一次,您可以在方法内部定义它,或者在更广泛的范围内定义多个类似的匹配项。

【讨论】:

  • 当我看到这个答案时,如果我正要点击 post :( @Alexey Romanov
  • @sebszyller 我知道这种感觉 :(
【解决方案2】:

只要在范围内有一个unapply 方法,它从您匹配的类型中获取一个参数,您就可以为此定义一个自定义提取器,例如

case class Big(foo: String, bar: String, baz: Option[String], x: Int, y: Int)

object SmallerBig {
  def unapply(x: Big): Option[(Option[String], Int)] = Some(x.baz, x.y)
}

val x = Big("a", "b", Some("c"), 1, 2)

x match {
  case Big(_, _, _, _, _) =>
  case SmallerBig(Some(a), b) =>
}

unapply方法的返回类型不能是Option,但是你返回的类型必须提供getisDefined这两个方法。

【讨论】:

    猜你喜欢
    • 2017-02-25
    • 2013-11-28
    • 2012-01-02
    • 2017-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    • 1970-01-01
    相关资源
    最近更新 更多