模式匹配与scala中的大小写匹配

时间:2015-10-30 06:49:58

标签: scala pattern-matching

我有这样的匹配声明:

val x = y match {
  case array: Array[Float] => call z
  case array: Array[Double] => call z
  case array: Array[BigDecimal] => call z 
  case array: Array[_] => show error
}

如何将此简化为仅使用两个case语句,因为前三个case语句执行相同的操作,而不是四个。

5 个答案:

答案 0 :(得分:1)

类型擦除实际上并没有让您有机会了解数组的输入方式。你应该做的是提取数组的头(第一个元素)并检查它的类型。例如,以下代码适用于我:

  List(1,2,3) match {
    case (a:Int) :: tail => println("yep")
  }

答案 1 :(得分:1)

这项工作,虽然不是很好:

def x(y: Array[_]) = y match {
  case a if a.isInstanceOf[Array[Double]] || 
            a.isInstanceOf[Array[Float]] || 
            a.isInstanceOf[Array[BigDecimal]] => "call z"
  case _ => "show error"
}

本来以为模式与“|”匹配如下所示就可以了。但是,这会使模式类型与 Array [Float] Array [BigDecimal] 上的预期类型不兼容。可能是在这个单一案例中它可以起作用的泛型匹配没有得到如此多的关注:

def x(y: Array[_ <: Any]) = y match {
  case a @ (_:Array[Double] | _:Array[Float] | _:Array[BigDecimal]) => "call z"
  case a: Array[_] => "show error"
}

答案 2 :(得分:0)

可能有点帮助:

import reflect.runtime.universe._

object Tester {
 def test[T: TypeTag](y: Array[T]) = y match {
   case c: Array[_] if typeOf[T] <:< typeOf[AnyVal] => "hi"
   case c: Array[_] => "oh"
 }
}

scala> Tester.test(Array(1,2,3))
res0: String = hi

scala> Tester.test(Array(1.0,2.0,3.0))
res1: String = hi

scala> Tester.test(Array("a", "b", "c"))
res2: String = oh

答案 3 :(得分:0)

您可以按如下方式获取数组元素类(对于非数组类型,它将是null):c.getClass.getComponentType。所以你可以写:

if (Set(classOf[Float], classOf[Double], classOf[BigDecimal]).contains(c.getClass.getComponentType)) {
  // call z
} else {
  // show error
}

不过特别是Scala&#39; ish;我认为@ thoredge的答案是最好的。

答案 4 :(得分:0)

您还可以先检查Array是否为空,如果没有,只需检查Array.head上的模式匹配......如下所示:

def x(y: Array[_]) = {
    y.isEmpty match {
      case true => "error"
      case false => y.head match {
         case a:Double | a:BigInt => do whatever
         case _ => "error"  
      }
    }
}