我想在Seq中寻找一个特定的模式。我试图在同一时间使用:+和+:运算符,但它似乎无法工作,即使它编译,现在我必须首先依赖'dropwhile'操作,然后在集合的开头模式匹配。
是不是可以在Scala中写出类似的内容? 'from'和'to'是现有变量
case beginColl :+ `from` +: someElement +: `to` +: tail => true
编辑:它是一个对象的Seq,而不是一个列表
答案 0 :(得分:1)
这将永远不会在该定义中起作用,因为除了unapplySeq
的结果中的尾部之外,您不能通配任何子序列。
但是,让我建议一个解决方法。
让我们定义这个帮手:
object Span {
class Spanner[T](pred: T => Boolean) {
def unapply(seq: Seq[T]) = for {
idx <- Some(seq.indexWhere(pred)) if idx >= 0
(start, elem +: end) = seq.splitAt(idx)
} yield (start, end)
}
def apply[T](pred: T => Boolean) = new Spanner(pred)
}
这允许我们定义更多有趣的匹配器,如此函数:
def splitter[T](from:T, to:T): PartialFunction[Seq[T], Seq[Seq[T]]] = {
val From = Span[T](_ == from)
val To = Span[T](_ == to)
{
case From(prefix, To(middle, postfix)) => Seq(prefix, middle, postfix)
}
}
因此,如果我们专注于:
val mySplitter = splitter("from", "to").lift
我们可以得到适当的结果:
mySplitter(Seq("1", "2", "to", "3", "4", "from", "5", "6")) // None
mySplitter(Seq("1", "2", "from", "3", "4", "to", "5", "6")) // Some(List(List(1, 2), List(3, 4), List(5, 6)))
让我们试着澄清编译器如何理解你的语法,让我们定义
def splitter2(from: AnyRef, to: AnyRef): PartialFunction[Seq[_], AnyRef] = {
case beginColl :+ `from` +: someElement +: `to` +: tail => (beginColl, someElement, tail)
}
val mySplitter2 = splitter2("from", "to").lift
所以,如果我们尝试匹配
mySplitter2(Seq("1", "2", "from", "3", "4 ", "to", "5", "6"))
我们肯定会得到None
但如果我们尝试
mySplitter2(Seq("1", "2", Seq("from", "3", "to", "4", "5")))
我们突然得到Some(...)
所以编译器只是把你的表达式理解为_match元素为
beginColl :+ __last
然后将__last
与
`from` +: someElement +: `to` +: tail
基本上验证这是非空的Seq
最后一个元素是
另一个Seq
由至少三个元素组成,其中第一个和第三个元素是from
和to
答案 1 :(得分:0)
我认为您可能需要识别这样的序列:
val test = Seq("x", "from", "y", "to", "z")
test match {
case _ :: "from" :: _ :: "to" :: _ => true
case _ => false
}
但是,由于您需要知道序列是否具有特定的特征,我会尝试这样做:
test match {
case list if (list.indexOf("from") < list.indexOf("to")) => true
case _ => false
}
答案 2 :(得分:0)
这应该有效:
case Seq(_, `from`, _, `to`, _*) => true
编辑:
如果'from'之前有更多元素,dropWhile是一个很好的解决方案,另一种方法(但效率较低)可能是:
def matchSeq[T](s: Seq[T]): Boolean = s match {
case Seq(_, `from`, _, `to`, _*) => true
case Seq(a, b@_*) => matchSeq(b)
case _ => false
}
答案 3 :(得分:0)
您可以使用containsSlice
检查序列是否包含子序列,或者您可以比较要查找的元素的索引。即:
val test = Seq("x", "from", "y", "to", "z")
val test2 = Seq("u", "w", "x", "from", "y", "to", "z")
test match {
case s if s.indexOf("to") - s.indexOf("from") == 2 => true
case _ => false
} //true in both cases.