我希望匹配序列中的序列,如ex 1或ex 2;
List(1, 2, 3, 4) match {
case 1 :: List(_*) :: 4 :: tail => // Ex 1
case 1 :: (seq : List[Int]) :: 4 :: tail => // Ex 2
case _ =>
}
这是fixed length sequence pattern _*
的变体。与_*
一样,我并不关心内部模式的内容,但重要的是长度可以变化,模式被前缀包围(例如1
以上)和后缀(如4
)。
我的问题是,如果您有任何诡计通过一些狡猾的unapply
魔法做到这一点,或者您只是迭代列表以手动搜索序列。
提前致谢! : - )
答案 0 :(得分:2)
这实际上超出了应该使用模式匹配的范围。即使您可以使用一组自定义unapply
方法来执行您想要的操作,但是匹配是否贪婪等等也不会显而易见。
但是,如果您真的想要,可以按照以下步骤(例如):
import scala.collection.SeqLike
class Decon[A](a0: A, a1: A) {
def unapply[C <: SeqLike[A, C]](xs: C with SeqLike[A, C]): Option[(C, C)] = {
xs.span(_ != a1) match {
case (a0 +: pre, a1 +: post) => Some((pre,post))
case _ => None
}
}
}
val Dc = new Decon(1,4)
scala> List(1,2,3,4,5) match { case Dc(pre, post) => (pre, post); case _ => (Nil, Nil) }
res1: (List[Int], List[Int]) = (List(2, 3),List(5))
必须将匹配的固定元素1
和4
的规范分开;否则,正常算法会要求unapply
返回值而不知道正在寻找什么,然后测试以确保它们是正确的。
答案 1 :(得分:1)
你可以这样做:
List(1,2,3,4) match {
case 1 :: tail if tail.last == 4 => println("Found it!")
}
但是,如果您在last
中检查LinearSeqOptimized
的实施情况:
def last: A = {
if (isEmpty) throw new NoSuchElementException
var these = this
var nx = these.tail
while (!nx.isEmpty) {
these = nx
nx = nx.tail
}
these.head
}
确实在迭代。这是因为List
继承自LinearSeq
,其经过优化可提供高效的head
和tail
操作。对于您想要执行的操作,最好使用IndexedSeq
实施,例如Vector
具有优化length
操作,在last
中使用:
override /*TraversableLike*/ def last: A = {
if (isEmpty) throw new UnsupportedOperationException("empty.last")
apply(length-1)
}
所以你可以这样做:
Vector(1,2,3,4) match {
case v if v.head == 1 && v.last == 4 => println("Found it!")
}