Scala是否允许使用这种提取器?

Sen*_*ess 5 scala unapply

假设我有这个系列:

val a = Array(Array(1,2,3,4,5),Array(4,5),Array(5),Array(1,2,6,7,8))
Run Code Online (Sandbox Code Playgroud)

有没有办法定义一个可以按以下方式工作的提取器:

a.foreach(e => {
   e match {
      case Array( ending with 5 ) => 
      case _ =>
   }
})
Run Code Online (Sandbox Code Playgroud)

对不起伪代码,但我不知道如何表达它.有没有办法匹配5个作为最后一个元素的东西?如果我想匹配第一个元素为1而最后一个元素为5的东西怎么办?这适用于各种长度的数组(请注意,我在示例中为我的数组特别选择了不同的长度).

谢谢!

par*_*tic 11

是的你可以:

object EndsWith {
  def unapply[A]( xs: Array[A] ) = 
    if( xs.nonEmpty ) Some( xs.last ) else None
}
Run Code Online (Sandbox Code Playgroud)

在你的例子上:

val a = Array(Array(1,2,3,4,5),Array(4,5),Array(5),Array(1,2,6,7,8))

a foreach { 
  case e @ EndsWith(5) => println( e.mkString("(",",",")" ) )
  case _ =>
}
Run Code Online (Sandbox Code Playgroud)

它按预期打印(1,2,3,4,5),(4,5)并且(5)

使用相同的方法,您可以编写一个提取器StartWith,然后添加一个方法,将它们组合在一个匹配两个条件的新提取器中.


dhg*_*dhg 9

a.foreach(e => {
   e match {
      case a: Array[Int] if a.last == 5 => 
      case _ =>
   }
})
Run Code Online (Sandbox Code Playgroud)

你可以做一些更好的事情来匹配第一个元素:

a.foreach(e => {
   e match {
      case Array(1, _*) => 
      case _ => 
   }
})
Run Code Online (Sandbox Code Playgroud)

不幸的是,@_*事情必须是数组参数列表中的最后一项.但是你可以在此之前进行匹配,因为你想要复杂.

scala> val Array(1, x @_*) = Array(1,2,3,4,5)
x: Seq[Int] = Vector(2, 3, 4, 5)

scala> val Array(1, b, 3, x @_*) = Array(1,2,3,4,5)
b: Int = 2
x: Seq[Int] = Vector(4, 5)
Run Code Online (Sandbox Code Playgroud)